在Java中解析ISO 8601日期格式,如2015-06-27T13:16:37.363Z



我正在尝试使用SimpleDateFormat解析String

这是我当前的代码:

public String getCreatedDateTime() {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ddEHH:mm:ss.zzzz");
    try {
        Date date = simpleDateFormat.parse("2015-06-27T13:16:37.363Z");
        return date.toString();
    } catch (ParseException e) {
        return "Error parsing date";
    }
}

正如您所看到的,我只是在parse()方法中放了一个常量用于测试目的。

所以,这就是我试图解析的:

2015-06-27T13:16:37.363Z

这是我正在使用的SimpleDateFormat模式:

yyyy-MM-ddEHH:MM:ss.zzzz

我一直收到ParseException。

我知道这是因为结尾处的zzzz,但我不知道363Z可能代表什么,所以我只使用了一些随机字母。坏主意。

我会非常感谢你的帮助。非常感谢。

尝试使用此模式(注意末尾的X和中间的"T"):

"yyyy-MM-dd'T'HH:mm:ss.SSSX"

来自Java的SimpleDateFormat文档:

ISO 8601时区:

为了解析;Z";被解析为UTC时区指示符。

并且,从描述不同特征的部分来看:

X-时区-ISO 8601时区

编辑

如果使用Android;X〃;不支持。

你可以使用这个模式(注意Z现在是字面意思):

"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

但是,您将获得当前时区的日期,如果需要,需要将其转换为UTC。

tl;dr

跳过格式设置模式。默认情况下使用标准ISO 8601格式。

Instant.parse( "2015-06-27T13:16:37.363Z" )

ISO 8601

您的字符串格式是由ISO8601标准正式定义的。

基本上,您的问题是这个问题的重复,将符合ISO 8601的字符串转换为java.util.Date.

备选方案

优生学的答案是正确的。

但您应该知道,与java捆绑在一起的旧java.util.Date/.Calendar/java.text.SimpleDateFormat类是出了名的麻烦,应该避免使用。

过时的类

这些旧类现在已经过时了,首先是第三方Joda Time库,现在是java 8及更高版本中内置的新java.Time包(教程)(灵感来自Joda Time,由JSR310定义,由ThreeTen Extra项目扩展)。

在解析/生成日期-时间值的字符串表示时,java.time和JodaTime都使用ISO8601标准作为默认值。因此,代码很简单,不需要自定义格式化程序对象不需要所有导致异常的格式处理

时区

java.time和JodaTime都有一个分区日期时间类,它可以理解其分配的时区(与java.util.date不同)。如果不分配,则会分配JVM当前的默认时区。

注意JVM的当前默认时区可以随时更改。它可以在部署时更改,默认为主机操作系统的设置。当JVM中任何应用程序的任何线程中的任何代码调用TimeZone.setDefault时,它可以在运行时的任何时刻更改。因此,最好明确指定所需/预期的时区。

java.time

字符串末尾的Z是祖鲁语的缩写,意思是UTC。Instant类可以直接解析该格式,以UTC表示时间线上的一个时刻,分辨率为纳秒。

String input = "2015-06-27T13:16:37.363Z";
Instant instant = Instant.parse( input );

将时区从UTC更改为所需/预期的时区。

ZoneID zone = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdtMontréal = instant.atZone( zone ) ;

如果您确实需要一个java.util.Date来实现互操作性,请转换。

java.util.Date utilDate = Date.from( zdtMontréal.toInstant() ) ;

Joda时间

JodaTime项目现在处于维护模式,团队建议迁移到java.Time类:

注意,从JavaSE8开始,用户被要求迁移到java.time(JSR-310)——JDK的核心部分,它取代了这个项目。

使用Joda Time 2.8.1的示例代码。

String input = "2015-06-27T13:16:37.363Z" ;
DateTimeZone zone = DateTimeZone.UTC ;  //  Or: DateTimeZone.forID( "America/Montreal" ) ;
DateTime dateTime = new DateTime( input, zone ) ;

如果您确实需要一个java.util.Date来实现互操作性,请转换。

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

关于java.time

java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.DateCalendar和&CCD_ 10。

要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。

现在处于维护模式的JodaTime项目建议迁移到java.Time类。

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*类。

从哪里获得java.time类?

  • Java SE 8Java SE 9Java SE 10爪哇SE 11及更高版本-标准Java API的一部分,具有捆绑实现。
    • Java 9添加了一些小功能和修复程序
  • Java SE 6Java SE 7
    • java.time的大部分功能都是后移植到Java6&7英寸ThreeTen背包
  • 安卓
    • java.time类的Android捆绑包实现的后续版本
    • 对于早期的Android(<26),ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…

ThreeTen Extra项目通过附加类扩展java.time。这个项目是将来可能添加到java.time的试验场。您可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等等。

最新更新