java.time.format.DateTimeParseException: 无法在索引处解析文本

java.time.format.DateTimeParseException: Text could not be parsed at index

这看起来很容易实现,但我没能做到。

我有一个 yyyyMMddHH 的字符串模式,我正在尝试将 2021061104 解析为 LocalDateTime

的实例

代码如下:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;


class Main {
    public static void main(String[] args) {
        String pattern = "yyyyMMddHH";
        String date = "2021061104";
        DateTimeFormatter formatter =
            new DateTimeFormatterBuilder()
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .parseLenient()
                .appendPattern(pattern)
                .toFormatter();
        LocalDateTime ldt = LocalDateTime.parse(date, formatter);
    }
}

它抛出这个异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2021061104' could not be parsed at index 8
        at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
        at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
        at java.time.LocalDateTime.parse(LocalDateTime.java:492)
        at Main.main(Main.java:22)

无法从输入中解析 HH 字段。
我看过 javadoc here 但这没有帮助。

为什么我有这个异常?如何解决?

编辑:

我无法删除.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)

约束条件如下:

由于这些限制,我无法删除 .parseDefaulting(ChronoField.HOUR_OF_DAY, 0),因为如果我这样做,我将无法将 yyyy-MM-dd 解析为 LocalDateTime here 的实例

嗯,我认为这是由 .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) 引起的。在进行任何解析之前,构建器会立即插入一个默认值。解析的时候hour部分已经有值,所以HH解析失败

此行为实际上在 the JavaDocs 中提到:

During parsing, the current state of the parse is inspected. If the specified field has no associated value, because it has not been parsed successfully at that point, then the specified value is injected into the parse result. Injection is immediate, thus the field-value pair will be visible to any subsequent elements in the formatter. As such, this method is normally called at the end of the builder.

强调我的。

因此,可能的解决方法是将 parseDefaulting 行移动到格式化程序生成器的末尾:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseLenient()
    .appendPattern(pattern)
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
    .toFormatter();

Here is a working example 将这些行移动到生成器的末尾。