【问题标题】:JSR310 Year.parse() throws DateTimeParseException with values < 1000JSR310 Year.parse() 抛出 DateTimeParseException 值 < 1000
【发布时间】:2020-09-06 11:40:44
【问题描述】:

我正在尝试使用 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)
[...]

我做错了什么?

【问题讨论】:

    标签: java jsr310


    【解决方案1】:

    需要补齐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");
    

    【讨论】:

    • 请提及Javadoc中提到的+/-前缀(因为Javadoc没有说需要填充年份)。
    • 但是 OP 不明白。您的回答显示了如何轻松地使循环工作,但异常的来源似乎丢失了,即使他引用了 Javadoc 的确切部分。
    • 这种行为(必须填充到 4 位)在 imo 中确实很奇怪,但这样就可以了。
    【解决方案2】:

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

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

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

    因此,即使您引用的 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
    

    所以Year 打印的格式 符合 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
    

    链接

    【讨论】:

      猜你喜欢
      • 2019-07-01
      • 1970-01-01
      • 2021-08-10
      • 2023-04-03
      • 2022-11-21
      • 2021-04-30
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多