gpt4 book ai didi

java-8 - 为什么 Java 8 DateTimeFormatter 在 ResolverStyle.STRICT 模式下允许不正确的月份值?

转载 作者:行者123 更新时间:2023-12-02 06:55:04 26 4
gpt4 key购买 nike

为什么这个测试通过了,而月份值却明显无效(13)?

@Test
public void test() {

String format = "uuuuMM";

String value = "201713";

DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT)
.parse(value);

}

使用临时查询时,会引发预期的 DateTimeParseException:

DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT)
.parse(value, YearMonth::from);

未指定 TemporalQuery 时会发生什么?

<小时/>

编辑:13 值似乎是一个特殊的值,正如我从 ΦXocę 웃 Пepeúpa ツ 的回答中了解到的那样(参见 Undecimber )。

但即使使用其他值(例如 50)也不会引发异常:

@Test
public void test() {

String format = "uuuuMM";

String value = "201750";

DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT)
.parse(value);

}

最佳答案

我在这里进行了一些调试,发现解析过程的一部分是根据格式化程序的时间顺序检查字段。

当您创建DateTimeFormatter时,by default它使用 IsoChronology ,用于解析日期字段。在此解决阶段,the method java.time.chrono.AbstractChronology::resolveDate被调用。

如果你看source ,您将看到以下逻辑:

if (fieldValues.containsKey(YEAR)) {
if (fieldValues.containsKey(MONTH_OF_YEAR)) {
if (fieldValues.containsKey(DAY_OF_MONTH)) {
return resolveYMD(fieldValues, resolverStyle);
}
....
return null;

由于输入仅包含字段,因此fieldValues.containsKey(DAY_OF_MONTH)返回false ,该方法返回 null 并且没有进行其他检查,如 Parsed class 中所示。 .

因此,在没有 TemporalQuery 的情况下解析 201750201713 时,由于上述逻辑,不会进行额外的检查,并且 parse 方法返回一个 java.time.format.Parsed 对象,如以下代码所示:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuuMM").withResolverStyle(ResolverStyle.STRICT);
TemporalAccessor parsed = fmt.parse("201750");
System.out.println(parsed.getClass());
System.out.println(parsed);

输出为:

class java.time.format.Parsed
{Year=2017, MonthOfYear=50},ISO

请注意,返回对象的类型是java.time.format.Parsed,打印它会显示已解析的字段(年和月)。

当您使用 TemporalQuery 调用 parse 时,Parsed 对象会传递给查询,并且它的字段会被验证(当然这取决于查询,但 API 内置查询始终有效)。

对于 YearMonth::from,它使用相应的 ChronoField( MONTH_OF_YEARYEAR )检查年份和月份是否有效。月份字段仅接受值 from 1 to 12 .

这就是为什么仅调用 parse(value) 不会引发异常,但使用 TemporalQuery 调用则会引发异常。

<小时/>

当所有日期字段(年、月和日)都存在时,检查上面的逻辑:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuuMMdd").withResolverStyle(ResolverStyle.STRICT);
fmt.parse("20175010");

这会抛出:

Exception in thread "main" java.time.format.DateTimeParseException: Text '20175010' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 50

由于所有日期字段都存在,fieldValues.containsKey(DAY_OF_MONTH) 返回 true,现在它检查它是否是有效日期(使用 resolveYMD method )。

关于java-8 - 为什么 Java 8 DateTimeFormatter 在 ResolverStyle.STRICT 模式下允许不正确的月份值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45839399/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com