tl;博士
Instant.parse( "2011-05-03T11:58:01Z" )
ISO 8601
实际上,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.
如果您有一个实际上是GregorianCalendar 的java.util.Calendar,请强制转换。
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 格式。他们甚至处理了一些在标准的后续版本中神秘消失的格式。
其他格式见LocalDate、OffsetDateTime等各个类的parse和toString方法。此外,请搜索 Stack Overflow,因为有 许多 示例和关于此主题的讨论。
- 应该能够轻松验证字符串以查看它是否是有效的 RFC 3339 日期
要验证输入字符串,请捕获DateTimeParseException。
try {
Instant instant = Instant.parse( "2011-05-03T11:58:01Z" ) ;
} catch ( DateTimeParseException e ) {
… handle invalid input
}
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获取 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。