【问题标题】:Java - SimpleDateFormatter Unparseable DateJava - SimpleDateFormat 不可解析的日期
【发布时间】:2014-02-26 23:57:02
【问题描述】:

使用 Java 的 SimpleDateFormat 和 Google 的 Gson 库,我试图从从 Minecraft 库目录下载的 Json 文件中解析日期。使用以下 SimpleDateFormat 解析日期时似乎存在问题:yyyy-MM-dd'T'HH:mm:ssZ

我还尝试了以下方法:

yyyy-MM-dd'T'HH:mm:ssX
yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssx

由于文件实际上是从网上下载的,我无法更改它。因此,解决方案必须在于将我的代码更改为不包含日期,或者从我的源代码中删除有问题的代码。这恰好是一个相当大的问题,因为我的应用程序在解析日期时死了,并且似乎是解析问题,而不是文件问题。

日期格式如下:

2013-12-18T00:41:38-0500
2013-10-25T15:00:00+02:00

以上两个日期都崩溃了。它们都来自不同的文件。我在网上浏览了多种解决方案,但似乎都没有解决它。

我什至在#technic 频道上询问并浏览了TechnicLauncher 源代码,但几乎没有任何帮助。而且由于我使用的课程实际上与 Technic Launcher 完全相同,这让我感到困惑。如果您想仔细阅读源代码,可以在这里查看:GitHub :: LauncherCore

【问题讨论】:

标签: java json date


【解决方案1】:

Java 7 - 使用格式代码 X

import java.text.SimpleDateFormat;

public class Test {
  public static void main(String[] args) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
    String date1 = "2013-12-18T00:41:38-0500";
    String date2 = "2013-10-25T15:00:00+08:00";

    try {
      System.out.println(dateFormat.parse(date1));      
      System.out.println(dateFormat.parse(date2));
    } catch (Exception e ) {
      System.out.println(e);
    }     
  }
}

产生输出

Wed Dec 18 05:41:38 GMT 2013
Fri Oct 25 08:00:00 BST 2013

冬天在爱尔兰跑步时。

【讨论】:

  • 2013-12-18T00:41:38-0500Wed Dec 18 00:41:38 GMT 2013 不同,因为时区是 GMT。不会是Wed Dec 18 05:41:38 GMT 2013。删除“Z”只是忽略时区,并假定 JVM 的默认时区
  • 这只是帮助我找到格式是否正确运行,它实际上并没有帮助解决我的问题。
  • 你说你的问题是当你使用'Z'后缀时它崩溃了。我提出的解决方案是使用“X”后缀来代替 a) 不会崩溃,b) 会给出正确的结果。
【解决方案2】:

Java 日期/时间是一个令人头疼的问题。无论如何,诀窍是我使用并且似乎可以工作,这两个 xml 日历解析器都与 SimpleDateFormat 相结合。不久前,我还在我的blog: a simple trick for date format 上发布了此内容,您可能也可以在那里使用。但无论如何,这就是答案。只需采用此方法并制作一些小推文并插入(替换)该 DateTypeAdapter 类的 deserializeToDate() 方法:

   private Date deserializeToDate(/*JsonElement*/String json) /*Json*/ParseException {
      Date d = null;
      String date = json; // json.getAsString();
      try {
         d = javax.xml.bind.DatatypeConverter.parseDateTime(date).getTime();
      } catch (Exception e) {} // ignore
      if (d == null) {
         SimpleDateFormat dateFormat = 
                  new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
         d = dateFormat.parse(date);      
      }
      return d;
   }

   @Test
   public void shouldParseXmlDateTime() {
      String date1 = "2013-12-18T00:41:38-0500";
      String date2 = "2013-10-25T15:00:00+08:00";

      try {
        System.out.println(deserializeToDate(date1));      
      } catch (Exception e ) {
        System.out.println(e);
      }     
      try {
         System.out.println(parse(date2));      
       } catch (Exception e ) {
         System.out.println(e);
       }     
   }

这应该产生:

Wed Dec 18 00:41:38 EST 2013
Fri Oct 25 03:00:00 EDT 2013

【讨论】:

  • 治疗头痛的阿司匹林:Joda-Timejava.time
  • 尽管这对其他人有用,但这并不能解决我的问题。我遇到的问题是我从文件中检索的日期在运行时会导致 JsonParseException。
  • 我知道你用这个去哪里了,你想让我修复 LauncherCore ......无论如何,你也可以做到......你所要做的就是:下载 LauncherCore,制作一些更改并重新包装它。您需要进行的更改更改在 DateTypeAdapter.deserializeToDate() 中?只需替换为我上面更改的方法即可。
  • 恐怕我不太明白我应该修复什么。
  • 是的,恐怕这实际上并没有改变任何东西。我得到完全相同的结果:Exception: JsonSyntaxException, Message: 2013-10-25T15:00:00+02:00
【解决方案3】:

tl;博士

直到错误被修复:

OffsetDateTime.parse( 
    "2013-12-18T00:41:38-0500" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" )
)

bug 修复后:

OffsetDateTime.parse( "2013-12-18T00:41:38-0500" )

java.time

现代方法使用 java.time 类。

OffsetDateTime odt = OffsetDateTime.parse( "2013-10-25T15:00:00+02:00" ) ;

应该也适用于2013-12-18T00:41:38-0500。不幸的是,事实并非如此。 OffsetDateTime 类有一个错误,当从 UTC 偏移的部分在小时和分钟之间缺少可选冒号时会咬人。所以2013-12-18T00:41:38-05:00 可以工作,但2013-12-18T00:41:38-0500 不行。

作为一种解决方法,定义格式模式。

String input = "2013-12-18T00:41:38-0500" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;

odt.toString(): 2013-12-18T00:41:38-05:00

有关更多讨论,请参阅类似问题:


乔达时间

更新:Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。本节原封不动地保留为历史。

仅供参考,如果您使用 Joda-Time 而不是臭名昭著的麻烦 java.util.Date/Calendar 类,则可以简单地将 ISO 8601 字符串直接传递给 DateTime 构造函数,而无需格式化程序。 Joda-Time 使用 ISO 8601 作为其默认值。

DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( "2007-03-01T13:00:00Z", timeZone );

如果您想在不调整时区的情况下以 UTC 工作,只需从上面的代码中省略 timeZone 内容。

如果您需要 java.util.Date 对象用于其他目的,请从 Joda-Time 转换。

java.util.Date date = dateTime.toDate();

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    相关资源
    最近更新 更多