无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date相关的知识,希望对你有一定的参考价值。
我对java 8日期格式/解析功能有点沮丧。我试图找到Jackson配置和DateTimeFormatter
来解析"2018-02-13T10:20:12.120+0000"
字符串到任何Java 8日期,并没有找到它。
这是java.util.Date
示例,它工作正常:
Date date = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ")
.parse("2018-02-13T10:20:12.120+0000");
相同的格式不适用于新的日期时间api
ZonedDateTime dateTime = ZonedDateTime.parse("2018-02-13T10:20:12.120+0000",
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ"));
我们应该能够以适合FE UI应用程序的任何格式格式化/解析日期。也许我误解或错误的东西,但我认为java.util.Date
提供更多的格式灵活性和更容易使用。
tl;dr
直到bug被修复:
OffsetDateTime.parse(
"2018-02-13T10:20:12.120+0000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" )
)
当错误修复时:
OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" )
Details
您使用的是错误的类。
避免麻烦的旧遗留类,如Date
,Calendar
和SimpleDateFormat
。现在由java.time类取代。
您使用的ZonedDateTime
类很好,它是java.time的一部分。但它适用于全时区。你的输入字符串只有一个offset-from-UTC。相比之下,全时区是对不同时间点,过去,现在和将来的区域有效的偏移的集合。例如,在北美大部分地区使用夏令时(DST)时,每年两次的偏移量会在春季变小,因为我们将时钟向前移动一小时,而在秋季时我们将时钟移回一个更长的值。小时。
OffsetDateTime
对于偏移而不是时区,请使用OffsetDateTime
类。
您的输入字符串符合ISO 8601标准。在解析/生成字符串时,java.time类默认使用标准格式。因此无需指定格式化模式。
OffsetDateTime odt = OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" );
那应该是有效的。遗憾的是,Java 8中存在一个错误(至少通过Java 8 Update 121),该类无法解析在小时和分钟之间省略冒号的偏移量。所以虫子咬了+0000
而不是+00:00
。因此,在修复程序到达之前,您可以选择两种解决方法:(a)hack,操作输入字符串,或(b)定义显式格式化模式。
hack:操纵输入字符串以插入冒号。
String input = "2018-02-13T10:20:12.120+0000".replace( "+0000" , "+00:00" );
OffsetDateTime odt = OffsetDateTime.parse( input );
DateTimeFormatter
更强大的解决方法是在DateTimeFormatter
对象中定义和传递格式化模式。
String input = "2018-02-13T10:20:12.120+0000" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );
odt.toString():2018-02-13T10:20:12.120Z
顺便说一句,这里有一个提示:我发现使用许多协议和库,如果你的偏移总是有冒号,你的生活会更容易,总是有小时和分钟(即使分钟为零),并且总是使用填充零(-05:00
而不是-5
)。
DateTimeFormatterBuilder
对于通过DateTimeFormatterBuilder
创建的更灵活的格式化程序,请参阅this excellent Answer重复的问题。
Instant
如果要使用始终为UTC(并且应该)的值,请提取Instant
对象。
Instant instant = odt.toInstant();
ZonedDateTime
如果你想通过某个地区的wall-clock time镜头观看那一刻,请应用时区。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
看到这个code run live at IdeOne.com。
在许多问题的答案中,所有这些都已被多次涵盖。请在发布前彻底搜索Stack Overflow。你会发现很多甚至数百个例子。
About 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 driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
- Java SE 8,Java SE 9,Java SE 10,以及之后 内置。 带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小功能和修复。
- Java SE 6和Java SE 7 大部分java.time功能都在ThreeTen-Backport中反向移植到Java 6和7。
- Android 更高版本的android捆绑java.time类的实现。 对于早期的Android(<26),ThreeTenABP项目适应ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…。
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
和more。
以上是关于无法解析ISO 8601格式的字符串,缺少冒号的冒号,到Java 8 Date的主要内容,如果未能解决你的问题,请参考以下文章
在django tables2中解析ISO 8601日期格式
c++11:使用HowardHinnant/date.h解析ISO8601格式字符串,并解决时区问题
如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?
如何在 Swift 中解析/创建格式为小数秒 UTC 时区(ISO 8601、RFC 3339)的日期时间戳?