【问题标题】:Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java [duplicate]在 Java 中解析 ISO 8601 日期格式,如 2015-06-27T13:16:37.363Z [重复]
【发布时间】:2015-06-27 16:30:48
【问题描述】:

我正在尝试使用 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 可能代表什么,所以我只是使用了一些随机字母。坏主意。

非常感谢您的帮助。谢谢!

【问题讨论】:

标签: java date simpledateformat iso8601


【解决方案1】:

试试这个模式(注意末尾的 X 和中间的“T”):

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

来自 Java 的SimpleDateFormat's documentation

ISO 8601 时区:

...

对于解析,“Z”被解析为 UTC 时区指示符。

而且,从描述不同字符的部分来看:

X - 时区 - ISO 8601 时区

编辑

如果使用 Android,则不支持“X”。

您可以使用这种模式(注意 Z 现在是文字):

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

但是你会得到你当前时区的日期,如果需要,你需要将它转换为 UTC。

【讨论】:

  • 感谢您的回答。遗憾的是它还没有工作。我得到 IllegalArgumentException: Unknown pattern character X 与您的模式。这很奇怪,因为从文档中可以看出 X 显然是一个 pttern 字符。
  • 您使用的是哪个版本的 Java?它是 Java SE 还是 Android?
  • 我使用的是 jdk1.8.0_40,这是 Android。
  • 好吧,Android 似乎不支持“X”。我会更新我的答案,并包括 Android 的一部分。
  • 您可以使用 simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) 设置解析/格式化的时区,以明确您的意图并避免解析后的转换。 docs.oracle.com/javase/7/docs/api/java/text/…
【解决方案2】:

tl;博士

跳过格式化模式。默认使用标准ISO 8601 格式。

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

ISO 8601

您的字符串格式由ISO 8601 标准正式定义。

基本上你的问题是这个问题的副本,Converting ISO 8601-compliant String to java.util.Date

替代方案

The Answer by eugenioy 是正确的。

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

过时的类

那些旧类现在已经过时了,首先是第三方 Joda-Time 库,现在是 Java 8 及更高版本中内置的新 java.time package (Tutorial)(受 Joda-Time 启发,由 @ 定义) 987654329@,由ThreeTen-Extra 项目扩展)。

在解析/生成日期时间值的字符串表示时,java.time 和 Joda-Time 都使用 ISO 8601 标准作为它们的默认值。所以代码很简单,不需要自定义格式化对象。 不需要所有导致异常的格式。

时区

java.time 和 Joda-Time 都有一个分区日期时间类,该类可以理解其分配的时区(与 java.util.Date 不同)。如果不指定一个,则指定 JVM 当前的默认时区。

请注意,JVM 当前的默认时区可以随时更改。它可以在部署时更改,默认为主机操作系统设置。当 JVM 内任何应用程序的任何线程中的任何代码调用 TimeZone.setDefault 时,它可以在运行时的任何时刻发生变化。所以最好明确分配一个期望/预期的时区。

java.time

字符串末尾的 Z 是 Zulu 的缩写,表示 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-Time

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

请注意,从 Java SE 8 开始,用户被要求迁移到 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 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

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

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

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

从哪里获得 java.time 类?

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

【讨论】:

  • 谢谢您,您的回答非常有用。
猜你喜欢
  • 2021-12-15
  • 2019-02-11
  • 1970-01-01
相关资源
最近更新 更多