JSR310 Year.parse() 抛出值< 1000 的 DateTimeParseException



我正在尝试使用java.time.Year.parse()解析 0 到 1000 范围内的年份字符串值,但是解析失败并java.time.format.DateTimeParseException: Text '999' could not be parsed at index 0.

Year.parse的javadoc指出:

Obtains an instance of Year from a text string such as 2007. 
The string must represent a valid year. Years outside the range 0000 to 9999 
must be prefixed by the plus or minus symbol.

重现此问题的示例测试:

@Test
public void parse_year() {
for (int i = 2000; i >= 0; i--) {
System.out.println("Parsing year: " + i);
Year.parse(String.valueOf(i));
}
}

当达到第999年时,测试会引发异常:

Parsing year: 1003
Parsing year: 1002
Parsing year: 1001
Parsing year: 1000
Parsing year: 999
java.time.format.DateTimeParseException: Text '999' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.Year.parse(Year.java:292)
at java.time.Year.parse(Year.java:277)
[...]

我做错了什么?

需要填充到 4 位数字

Year.parse(String.format("%04d", i));
Parsing year: 2000
Parsing year: ....
Parsing year: 4
Parsing year: 3
Parsing year: 2
Parsing year: 1
Parsing year: 0

如果你想在第 0 年之前解析,你可以使用

Year.parse("-0001");

你在java.time中发现了一个非常奇特的不一致。

首先,对于你观察到的行为,我认为这是有道理的。java.time 的类通常解析 ISO 8601 格式最常见的变体。一年的ISO 8601格式是(来自维基百科,底部的链接(:

ISO 8601 规定至少要避免四位数的年份 [YYYY] 2000年的问题。因此,它代表从 0000 到 9999年,0000年等于公元前1年和所有其他公元。

因此,即使您引用的Year.parse()文档对此不是很清楚,但至少 4 位数字的要求取自 ISO 8601,这肯定是故意的。

java.time 的其他类也有相同的要求。

LocalDate.parse("999-12-31");
Exception in thread "main" java.time.format.DateTimeParseException: Text '999-12-31' could not be parsed at index 0

到目前为止,java.time是一致的。

对我来说,尝试Year.toString方法时感到惊讶。java.time 类的toString方法通常也打印 ISO 8601 格式。

System.out.println(Year.of(999).toString());

输出为:

999

SoYear打印的格式不符合ISO 8601,更令人惊讶的是,它无法使用其单参数parse方法解析回的格式。这是我在任何java.time类中都没有想到的。

如果要解析少于 4 位数字的年份,只需使用格式化程序:

DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("u");
System.out.println(Year.parse("999", yearFormatter));
System.out.println(Year.parse("0", yearFormatter));
999
0

链接

  • 维基百科文章:ISO 8601

相关内容

  • 没有找到相关文章

最新更新