cla*_*lay 9 java iso8601 java-8
为什么JDK8 DateTime库似乎无法解析有效的iso8601日期时间strings?它在时区偏移上窒息,表示为"+01"而不是"+01:00"
这有效:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01:00")
Run Code Online (Sandbox Code Playgroud)
这会抛出一个解析异常:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01")
Run Code Online (Sandbox Code Playgroud)
来自iso8601维基百科页面:
与UTC的偏移量以与"Z"相同的方式附加到时间,格式为±[hh]:[mm],±[hh] [mm]或±[hh].因此,如果描述的时间比UTC早一个小时(例如冬季柏林的时间),则区域指示符将为"+01:00","+ 0100"或简称为"+01".
编辑:这看起来像JDK中的实际合法错误.
https://bugs.openjdk.java.net/browse/JDK-8032051
哇,经过多年测试新的日期时间后,我认为他们会发现一些如此明显的东西.我还认为JDK作者类型非常严格,可以使用更好的自动化测试套件.
更新:这在当前的jdk-9版本中完全修复.我刚刚确认了.上面显示的完全相同的解析命令在当前的jdk-8构建中失败,并且在jdk-9中完美地工作.
附录:FWIW,基于ISO-8601的RFC 3339,不允许这个简写.您必须在时区偏移中指定分钟.
您使用此默认格式化程序:ISO_OFFSET_DATE_TIME(因为 parse 2015-08-18T00:00+01:00)。
在文档中:
这将返回一个不可变的格式化程序,能够格式化和解析 ISO-8601 扩展偏移日期时间格式。[...]
偏移量 ID。如果偏移量有秒,那么即使这不是 ISO-8601 标准的一部分,它们也会被处理。解析不区分大小写。
它是(您仅将其用于此默认格式化程序):
ID 是偏移量的标准 ISO-8601 格式字符串的微小变化。有以下三种格式:
- Z - UTC (ISO-8601)
- +hh:mm 或 -hh:mm - 如果秒为零 (ISO-8601)
- +hh:mm:ss 或 -hh:mm:ss - 如果秒非零(不是 ISO-8601)(不
+hh喜欢 ISO-8601)。
看来 java.time (JDK 8) 并没有完全实现 ISO-8601。
这:
java.time.ZonedDateTime.parse("2015-08-18T00:00+01:00"); // works
Run Code Online (Sandbox Code Playgroud)
对应于(大致来自 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
Run Code Online (Sandbox Code Playgroud)
您可以使用DateTimeFormatterBuilder创建自己的DataTimeFormatter。
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
Run Code Online (Sandbox Code Playgroud)
使用appendPattern(字符串模式)代替appendOffsetId()并设置'X'或'x'。
现在,您可以使用您的 datatime 2015-08-18T00:00+01。
或者...使用默认 ISO_OFFSET_DATE_TIME 并添加 postfix :00。
java.time.ZonedDateTime.parse("2015-08-18T00:00+01" + ":00");
Run Code Online (Sandbox Code Playgroud)
但这最后一个解决方案很糟糕。
这在当前的 jdk-9 版本中已完全修复。我刚刚确认。上面显示的完全相同的解析命令在当前的 jdk-8 构建中失败,但在 jdk-9 中完美运行。
\n\n使用新的 jdk-9 shell:
\n\n\xe2\x9e\x9c jdk-9 bin/jshell\n| Welcome to JShell -- Version 9-ea\n| For an introduction type: /help intro\n\njshell> java.time.ZonedDateTime.parse("2015-08-18T00:00+01")\n$1 ==> 2015-08-18T00:00+01:00\nRun Code Online (Sandbox Code Playgroud)\n