具有模式 "yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]" 的 DateTimeFormatter 的 DateTimeParseException

DateTimeParseException for DateTimeFormatter with pattern "yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]"

我想创建一个接受不同类型格式的 DateTimeFormatter,例如:“2018”、“2018-01-02”或“2018-01-02 10:15”。我试着像这样构建它:

DateTimeFormatter f1 = new DateTimeFormatterBuilder()
            .appendPattern("yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]")
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
            .toFormatter();

LocalDateTime.parse("2018-01", f1); // no problem
LocalDateTime.parse("2018", f1);    // exception

第二行给出了以下异常:

java.time.format.DateTimeParseException: Text '2018' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {Year=2018},ISO of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)

除了简单的“2018”之外,此格式化程序适用于我的所有案例。谁能告诉我为什么?

奇怪的是,下一个代码块的格式化程序将接受“2018”:

DateTimeFormatter f2 = new DateTimeFormatterBuilder()
        .appendPattern("yyyy[-MM[-d]]")
        .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
        .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
        .toFormatter();

LocalDate.parse("2018", f2);        // no problem

我认为你的方括号不匹配。

我试过你原来的例子:

DateTimeFormatter f1 = new DateTimeFormatterBuilder()
    .appendPattern("yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]")
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
    .toFormatter();

并得到与您相同的异常,但是当我再添加一个 ] 时,它按预期工作,所以这对我有用:

DateTimeFormatter f1 = new DateTimeFormatterBuilder()
    .appendPattern("yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]]")
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
    .toFormatter();

帮助比较:

    .appendPattern("yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]") // throws exception
    .appendPattern("yyyy[-MM[-d[ HH[:mm[:ss[.SSS]]]]]]") // works fine