Vir*_*nie 8 datetime-parsing java-8 java-time
为什么这个测试通过,而月份值显然是无效的(13)?
@Test
public void test() {
String format = "uuuuMM";
String value = "201713";
DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT)
.parse(value);
}
Run Code Online (Sandbox Code Playgroud)
使用时态查询时,会DateTimeParseException抛出预期:
DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT)
.parse(value, YearMonth::from);
Run Code Online (Sandbox Code Playgroud)
没有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);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我在这里进行了一些调试,发现解析过程的一部分是根据格式化程序的年表来检查字段.
创建时DateTimeFormatter,默认情况下它使用an IsoChronology,用于解析日期字段.在此解析阶段,调用该方法java.time.chrono.AbstractChronology::resolveDate.
如果查看源代码,您将看到以下逻辑:
if (fieldValues.containsKey(YEAR)) {
if (fieldValues.containsKey(MONTH_OF_YEAR)) {
if (fieldValues.containsKey(DAY_OF_MONTH)) {
return resolveYMD(fieldValues, resolverStyle);
}
....
return null;
Run Code Online (Sandbox Code Playgroud)
由于输入只有年和月字段,fieldValues.containsKey(DAY_OF_MONTH)返回false,方法返回,null并且没有进行其他检查,如您在Parsed类中看到的那样.
因此,在解析201750或201713不解析时TemporalQuery,由于上面的逻辑而没有进行额外的检查,并且该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);
Run Code Online (Sandbox Code Playgroud)
输出是:
class java.time.format.Parsed
{Year = 2017,MonthOfYear = 50},ISO
请注意,返回的对象的类型是,java.time.format.Parsed并且打印它显示已解析的字段(年和月).
但是,当您parse使用a 调用时TemporalQuery,Parsed会将对象传递给查询并验证其字段(当然,这取决于查询,但API内置函数始终会验证).
在这种情况下YearMonth::from,它使用相应ChronoField的(MONTH_OF_YEAR和YEAR)检查年份和月份是否有效,而月份字段仅接受1到12的值.
这就是为什么只是调用parse(value)不会抛出异常,而是调用TemporalQuerydo.
只是在所有日期字段(年,月和日)出现时检查上面的逻辑:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuuMMdd").withResolverStyle(ResolverStyle.STRICT);
fmt.parse("20175010");
Run Code Online (Sandbox Code Playgroud)
抛出:
线程"main"中的异常java.time.format.DateTimeParseException:无法解析文本"20175010":MonthOfYear的值无效(有效值1 - 12):50
由于所有日期字段都存在,因此fieldValues.containsKey(DAY_OF_MONTH)返回true并现在检查它是否是有效日期(使用该resolveYMD方法).
| 归档时间: |
|
| 查看次数: |
511 次 |
| 最近记录: |