添加到DateTimeFormatterBuilder的Literal破折号导致解析失败

Mic*_*ael 9 java java-time java-9

我正在尝试创建一个DateTimeFormatter匹配以下示例(它实际上稍微复杂一些,但这应该无关紧要).

20180302-17:45:21
Run Code Online (Sandbox Code Playgroud)

我写了以下内容但它导致了一个例外:

new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.BASIC_ISO_DATE)
    .appendLiteral('-')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter()
    .parse("20180302-17:45:21");
Run Code Online (Sandbox Code Playgroud)

例外是:

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)
Run Code Online (Sandbox Code Playgroud)

它似乎是在结肠之间失败17:45,DateTimeFormatterBuilder.appendLiteral并没有提供任何线索.

如果我将文字更改为另一个字符,让我们说m,那么它工作正常:

new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.BASIC_ISO_DATE)
    .appendLiteral('m')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter()
    .parse("20180302m17:45:21");
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?假设我无法更改格式,我该如何解决?

评论表明这可能取决于版本.我正在使用JDK 9.0.1,它已在9.0.4上复制.

Ole*_*.V. 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");
Run Code Online (Sandbox Code Playgroud)

现在我知道了java.time.format.DateTimeParseException: Text '20180302Z17:45:21' could not be parsed at index 9.指数9我们的权利后Z,如此看来格式解析偏移,然后试图找到字面Z其中17是.

编辑:和解决方案?而不是使用BASIC_ISO_DATE附加模式:

.appendPattern("uuuuMMdd")
Run Code Online (Sandbox Code Playgroud)

现在解析也适用于Java 9.0.4.

编辑:进一步说明偏移的可选性:

System.out.println(
    LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
System.out.println(
    OffsetDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE)
);
Run Code Online (Sandbox Code Playgroud)

这印

20180305
20180305+0100
Run Code Online (Sandbox Code Playgroud)

所以在第一种情况下,没有可用的偏移量,它只是将它排除在外.在第二种情况下,如果有一种可用,它也会被打印(没有冒号).

开放式问题:为什么它在Java 8中有效?这真的是个bug吗?

引用:

  • 如果偏移量不可用于格式化或解析,则格式化完成.
  • 没有冒号的偏移ID.如果偏移量为秒,则即使这不是ISO-8601标准的一部分,也会处理它们.偏移解析是宽松的,允许分钟和秒是可选的.解析不区分大小写.

文档中BASIC_ISO_DATE

  • 可能与https://bugs.openjdk.java.net/browse/JDK-8066806相关,其中Java 9中处理的偏移格式比Java 8更多. (3认同)