添加到 DateTimeFormatterBuilder 的文字破折号导致解析失败
Literal dash added to DateTimeFormatterBuilder causes parsing to fail
我正在尝试创建一个 DateTimeFormatter
来匹配以下示例(它实际上比这个稍微复杂一些,但这应该无关紧要)。
20180302-17:45:21
我写了以下内容,但它导致异常:
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('-')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302-17:45:21");
例外情况是:
Exception in thread "main" java.time.format.DateTimeParseException: Text '20180302-17:45:21' could not be parsed at index 11
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1816)
17:45
和 DateTimeFormatterBuilder.appendLiteral
之间的冒号似乎失败了,没有提供任何线索。
如果我将字面量更改为另一个字符,比方说 m
,那么它工作正常:
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('m')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302m17:45:21");
这是怎么回事?假设我无法更改格式,我该如何修复它?
评论表明这可能与版本有关。我正在使用 JDK 9.0.1,它是 .
这与 DateTimeFormatter.BASIC_ISO_DATE
包含一个可选的偏移量 ID 这一事实有关。显然,您的格式化程序将 -17
解析为偏移量,然后解析为对象,因为在格式需要连字符的地方有一个冒号。
当您改用 m
时,它不能被解析为偏移量,因此与格式中的文字 m
相匹配,并且一切正常。
我尝试使用大写 Z
。 Z
也可以是偏移量 ID。
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('Z')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302Z17:45:21");
现在我得到了 java.time.format.DateTimeParseException: Text '20180302Z17:45:21' could not be parsed at index 9
。在 Z
之后索引 9 us,因此格式化程序似乎解析了偏移量,然后尝试在 17
所在的位置找到文字 Z
。
编辑:解决方案呢?而不是使用 BASIC_ISO_DATE
附加模式:
.appendPattern("uuuuMMdd")
现在解析也适用于 Java 9.0.4.
编辑:进一步说明偏移量的可选性:
System.out.println(
LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
System.out.println(
OffsetDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
此打印
20180305
20180305+0100
所以在第一种情况下,没有可用的偏移量,它只是将其排除在外。在第二种情况下,如果有的话,也会打印出来(不带冒号)。
未决问题:为什么它在 Java 8 中有效?这真的是一个错误吗?
引用:
- If the offset is not available to format or parse then the format is complete.
- The offset ID without colons. If the offset has seconds then they will be handled even though this is not part of the ISO-8601
standard. The offset parsing is lenient, which allows the minutes
and seconds to be optional. Parsing is case insensitive.
我将其作为错误提出,并已在 JDK-8199412 中得到确认。
我正在尝试创建一个 DateTimeFormatter
来匹配以下示例(它实际上比这个稍微复杂一些,但这应该无关紧要)。
20180302-17:45:21
我写了以下内容,但它导致异常:
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('-')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302-17:45:21");
例外情况是:
Exception in thread "main" java.time.format.DateTimeParseException: Text '20180302-17:45:21' could not be parsed at index 11
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1816)
17:45
和 DateTimeFormatterBuilder.appendLiteral
之间的冒号似乎失败了,没有提供任何线索。
如果我将字面量更改为另一个字符,比方说 m
,那么它工作正常:
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('m')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302m17:45:21");
这是怎么回事?假设我无法更改格式,我该如何修复它?
评论表明这可能与版本有关。我正在使用 JDK 9.0.1,它是
这与 DateTimeFormatter.BASIC_ISO_DATE
包含一个可选的偏移量 ID 这一事实有关。显然,您的格式化程序将 -17
解析为偏移量,然后解析为对象,因为在格式需要连字符的地方有一个冒号。
当您改用 m
时,它不能被解析为偏移量,因此与格式中的文字 m
相匹配,并且一切正常。
我尝试使用大写 Z
。 Z
也可以是偏移量 ID。
new DateTimeFormatterBuilder()
.append(DateTimeFormatter.BASIC_ISO_DATE)
.appendLiteral('Z')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter()
.parse("20180302Z17:45:21");
现在我得到了 java.time.format.DateTimeParseException: Text '20180302Z17:45:21' could not be parsed at index 9
。在 Z
之后索引 9 us,因此格式化程序似乎解析了偏移量,然后尝试在 17
所在的位置找到文字 Z
。
编辑:解决方案呢?而不是使用 BASIC_ISO_DATE
附加模式:
.appendPattern("uuuuMMdd")
现在解析也适用于 Java 9.0.4.
编辑:进一步说明偏移量的可选性:
System.out.println(
LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
System.out.println(
OffsetDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
此打印
20180305
20180305+0100
所以在第一种情况下,没有可用的偏移量,它只是将其排除在外。在第二种情况下,如果有的话,也会打印出来(不带冒号)。
未决问题:为什么它在 Java 8 中有效?这真的是一个错误吗?
引用:
- If the offset is not available to format or parse then the format is complete.
- The offset ID without colons. If the offset has seconds then they will be handled even though this is not part of the ISO-8601 standard. The offset parsing is lenient, which allows the minutes and seconds to be optional. Parsing is case insensitive.
我将其作为错误提出,并已在 JDK-8199412 中得到确认。