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

时间:2018-03-05 11:33:34

标签: java java-9 java-time

我正在尝试创建一个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:45DateTimeFormatterBuilder.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

2 个答案:

答案 0 :(得分:8)

这与DateTimeFormatter.BASIC_ISO_DATE包含可选偏移ID的事实有关。显然你的格式化程序将-17解析为偏移量,然后是对象,因为有一个冒号,格式需要连字符。

当你使用m代替时,这不能被解析为偏移量,因此匹配格式中的文字m,一切正常。

我尝试使用大写ZZ也可以是偏移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的一部分,它们也会被处理   标准。偏移解析是宽松的,允许分钟   和秒是可选的。解析不区分大小写。
  •   

来自the documentation of BASIC_ISO_DATE

答案 1 :(得分:0)

我将此作为一个错误提出,并且已在JDK-8199412中确认。