为什么 JDK8 DateTime 库似乎无法解析有效的 iso8601 日期时间字符串?它在表示为“+01”而不是“+01:00”的时区偏移量上窒息
这个有效:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01:00")
这会抛出一个解析异常:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01")
来自 iso8601 维基百科页面:
The offset from UTC is appended to the time in the same way that 'Z' was above, in the form ±[hh]:[mm], ±[hh][mm], or ±[hh]. So if the time being described is one hour ahead of UTC (such as the time in Berlin during the winter), the zone designator would be "+01:00", "+0100", or simply "+01".
编辑:这看起来像是 JDK 中真正合法的错误。
https://bugs.openjdk.java.net/browse/JDK-8032051
哇,在测试新的日期时间东西多年之后,我认为他们会发现如此明显的东西。我还认为 JDK 作者类型足够严格,可以使用更好的自动化测试套件。
更新:这在当前的 jdk-9 版本中已完全修复。我刚刚确认。上面显示的完全相同的解析命令在当前 jdk-8 构建中失败,但在 jdk-9 中完美运行。
附录:FWIW,基于 ISO-8601 的 RFC 3339,不允许使用这种缩写形式。您必须在时区偏移量中指定分钟数。
最佳答案
你 use此默认格式化程序:ISO_OFFSET_DATE_TIME (因为解析 2015-08-18T00:00+01:00
)。
在文档中:
This returns an immutable formatter capable of formatting and parsing the ISO-8601 extended offset date-time format. [...]
The offset ID. If the offset has seconds then they will be handled even though this is not part of the ISO-8601 standard. Parsing is case insensitive.
It's (您仅将此用于此默认格式化程序):
The ID is minor variation to the standard ISO-8601 formatted string for the offset. There are three formats:
- Z - for UTC (ISO-8601)
- +hh:mm or -hh:mm - if the seconds are zero (ISO-8601)
- +hh:mm:ss or -hh:mm:ss - if the seconds are non-zero (not ISO-8601) (don't
+hh
like ISO-8601).
似乎 java.time (JDK 8) 没有完全实现 ISO-8601。
这个:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01:00"); // works
对应于(大致来自源 JDK):
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder
.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendOffsetId()
.toFormatter();
java.time.ZonedDateTime.parse("2015-08-18T00:00+01:00", formatter); // it's same
您可以创建自己的 DataTimeFormatter与 DateTimeFormatterBuilder .
DateTimeFormatterBuilder builder2 = new DateTimeFormatterBuilder();
DateTimeFormatter formatter2 = builder2.parseCaseInsensitive()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("X") // eg.:
.toFormatter();
java.time.ZonedDateTime.parse("2015-08-18T00:00+01", formatter2); // here you set +01
代替 appendOffsetId() 使用 appendPattern(String pattern)并设置 'X' 或 'x'。
现在,您可以使用数据时间 2015-08-18T00:00+01
。
或者...使用默认的 ISO_OFFSET_DATE_TIME 并添加后缀 :00
。
java.time.ZonedDateTime.parse("2015-08-18T00:00+01" + ":00");
但最后一个是糟糕的解决方案。
关于java.time.ZonedDateTime.parse 和 iso8601?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32079459/