使用 STRICT 解析器样式时出现 DateTimeParseException 问题

Issue with DateTimeParseException when using STRICT resolver style

我正在尝试使用以下模式解析日期字符串:yyMMddSTRICT 解析器如下:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT);
LocalDate.parse(expiryDate, formatter);

我得到以下 DateTimeParseException:

java.time.format.DateTimeParseException: Text '160501' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2016, MonthOfYear=5, DayOfMonth=1},ISO of type java.time.format.Parsed

当我切换到默认解析样式时,即 ResolverStyle.SMART 它允许 2 月 30 日这样的日期。

有人可以帮忙吗?

严格的解析器需要一个纪元来配合 YearOfEra。将您的模式更改为使用 "u" 而不是 "y" 它将起作用,即。 "uuMMdd".

虽然 JodaStephen 很好地解释了异常的原因并给出了一个好的解决方案(使用 uu 而不是 yy),但我提供了一些其他可能的解决方案:

  1. 您可能不想要的一个显而易见的方法:将解析器样式保留为 SMART(默认值)。换句话说,要么完全省略 .withResolverStyle(ResolverStyle.STRICT),要么将其更改为 .withResolverStyle(ResolverStyle.SMART).
  2. 提供默认纪元。

这里是第二个选项的代码示例:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("yyMMdd")
            .parseDefaulting(ChronoField.ERA, 1)
            .toFormatter()
            .withResolverStyle(ResolverStyle.STRICT);

    String expiryDate = "160501";
    LocalDate result = LocalDate.parse(expiryDate, formatter);
    
    System.out.println(result);

输出为:

2016-05-01

与在格式模式中使用 uu 相比,最后一个解决方案可能有所不同:

  1. 它允许我们使用提供给我们的格式模式,我们无法控制是使用模式字母 u 还是 y
  2. 使用模式字母 y 如果字符串包含负年份,它将失败并出现异常。根据您的情况和要求,这可能是可取的或不可接受的。

编辑:parseDefaulting() 的第二个参数也可以写成 IsoEra.CE.getValue() 而不仅仅是 1 以表明我们正在指定 当前时代(CE;通常也称为 Anno DominiAD)。