我正在尝试解析作为值从 HTML5 datetime
输入字段返回的日期。在 Opera 中尝试查看示例。返回的日期如下所示: 2011-05-03T11:58:01Z
。
我想将其解析为 Java 日期或日历对象。
理想情况下,解决方案应具有以下内容:
- 没有外部库(罐子)
- 处理所有可接受的 RFC 3339 格式
- 一个字符串应该能够很容易地被验证以查看它是否是一个有效的 RFC 3339 日期
原文由 Adam 发布,翻译遵循 CC BY-SA 4.0 许可协议
我正在尝试解析作为值从 HTML5 datetime
输入字段返回的日期。在 Opera 中尝试查看示例。返回的日期如下所示: 2011-05-03T11:58:01Z
。
我想将其解析为 Java 日期或日历对象。
理想情况下,解决方案应具有以下内容:
原文由 Adam 发布,翻译遵循 CC BY-SA 4.0 许可协议
Instant.parse( "2011-05-03T11:58:01Z" )
实际上, RFC 3339 只是实际标准 ISO 8601 自称的“配置文件”。
RFC 的不同之处在于它故意违反 ISO 8601 以允许零小时的负偏移量 ( -00:00
) 并赋予其语义“偏移量未知”。这种语义对我来说似乎是一个非常糟糕的主意。我建议坚持更明智的 ISO 8601 规则。在 ISO 8601 中,完全没有偏移量意味着偏移量是未知的——一个显而易见的意思,而 RFC 规则是深奥的。
现代 java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。
您的输入字符串代表 UTC 中的一个时刻。最后的 Z
是 Zulu
的缩写,表示 UTC。
Instant
(不是 Date
)现代类 Instant
代表 UTC 中的一个时刻。此类替换 java.util.Date
,并使用纳秒而不是毫秒的更精细分辨率。
Instant instant = Instant.parse( "2011-05-03T11:58:01Z" ) ;
ZonedDateTime
(不是 Calendar
)要通过某个地区(时区)的人们使用的挂钟时间查看同一时刻,请应用 ZoneId
以获得 ZonedDateTime
。此类 ZonedDateTime
替换了 java.util.Calendar
类。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, different wall-clock time.
我强烈建议尽可能避免使用遗留的日期时间类。但是,如果您必须与尚未更新到 java.time 的旧代码进行互操作,则可以来回转换。调用添加到 旧 类的新方法。
Instant
替换 java.util.Date
。
java.util.Date myJUDate = java.util.Date.from( instant ) ; // From modern to legacy.
Instant instant = myJUDate.toInstant() ; // From legacy to modern.
ZonedDateTime
替换 GregorianCalendar
。
java.util.GregorianCalendar myGregCal = java.util.GregorianCalendar.from( zdt ) ; // From modern to legacy.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // From legacy to modern.
如果你有一个 java.util.Calendar
实际上是一个 GregorianCalendar
,演员。
java.util.GregorianCalendar myGregCal = ( java.util.GregorianCalendar ) myCal ; // Cast to the concrete class.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // From legacy to modern.
关于您的问题的具体问题……
java.time 类内置于 Java 8、9、10 及更高版本中。后来的Android中也包含了一个实现。对于早期的 Java 和早期的 Android,请参阅本答案的下一部分。
各种 java.time 类处理我所知道的每一种 ISO 8601 格式。他们甚至处理了一些从标准的后续版本中神秘消失的格式。
For other formats, see the parse
and toString
methods of the various classes such as LocalDate
, OffsetDateTime
, and so on.此外,搜索 Stack Overflow,因为有 很多 关于此主题的示例和讨论。
要验证输入字符串,陷阱 DateTimeParseException
。
try {
Instant instant = Instant.parse( "2011-05-03T11:58:01Z" ) ;
} catch ( DateTimeParseException e ) {
… handle invalid input
}
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 旧 日期时间类,例如 java.util.Date
、 Calendar
和 SimpleDateFormat
。
现在处于 维护模式 的 Joda-Time 项目建议迁移到 java.time 类。
要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规范是 JSR 310 。
您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要 java.sql.*
类。
在哪里获取 java.time 类?
ThreeTen-Extra 项目用附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 Interval
、 YearWeek
、 YearQuarter
等等。
原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
刚刚发现google在Google HTTP Client Library中实现了Rfc3339 parser
https://github.com/google/google-http-java-client/blob/dev/google-http-client/src/main/java/com/google/api/client/util/DateTime.java
经过测试。它可以很好地解析不同的亚秒级时间片段。