我正在尝试创建一个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,它是been reproduced on 9.0.4。
答案 0 :(得分:8)
这与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我们,因此格式化程序似乎会解析偏移量,然后尝试找到Z
所在的文字17
。
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中有效?这真的是个错误吗?
引用:
- 如果无法格式化或解析偏移量,则表示格式已完成。
- 没有冒号的偏移ID。如果偏移量为秒,那么即使它不是ISO-8601的一部分,它们也会被处理 标准。偏移解析是宽松的,允许分钟 和秒是可选的。解析不区分大小写。
答案 1 :(得分:0)
我将此作为一个错误提出,并且已在JDK-8199412中确认。