Java 11 上的 DateTimeParseException 但适用于 Java 10

DateTimeParseException on Java 11 but works on Java 10

下面的测试用例在Java10下完美运行:

import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;

class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().
          appendPattern("EEE, dd MMM yyyy HH:mm:ss zzz").
          toFormatter();
        Instant result = dateFormatter.parse("Sat, 29 Sep 2018 20:49:02 GMT", Instant::from);
        System.out.println("Result: " + result);
    }
}

但在 Java 11 下我得到:

Exception in thread "main" java.time.format.DateTimeParseException: Text 'Sat, 29 Sep 2018 20:49:02 GMT' could not be parsed at index 0
        at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
        at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
        at Test.main(Test.java:13)

怎么回事?

UPDATE:将 toFormatter() 替换为 toFormatter(Locale.US) 可解决问题。我猜这个问题与 https://bugs.openjdk.java.net/browse/JDK-8206980 有关。此问题已在 Java 11 build 23 中标记为已修复,但我是 运行

openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

这个版本不应该解决这个问题吗?

UPDATE2:如果您无法重现问题,请尝试将 toFormatter() 替换为 toFormatter(Locale.CANADA)

DateTimeFormatter.RFC_1123_DATE_TIME

您的日期时间字符串在 RFC 822/RFC 1123 format. Instead of building your own formatter use the built-in DateTimeFormatter.RFC_1123_DATE_TIME:

    Instant result = DateTimeFormatter.RFC_1123_DATE_TIME
            .parse("Sat, 29 Sep 2018 20:49:02 GMT", Instant::from);
    System.out.println("Result: " + result);

输出为:

Result: 2018-09-29T20:49:02Z

根据 RFC 规范的要求,此 RFC 1123 格式化程序始终使用英文。我什至尝试将我的默认语言环境设置为 Locale.CANADA_FRENCH,代码仍然有效。

你的代码出了什么问题?

In Java 11 Java 期望星期几和月份的缩写在 Locale.CANADA 中用点书写:Sat.Sep. 而不是 SatSep。在 Java 10 中,它们应该没有点,所以这里解析有效。不同之处可能在于 CLDR 数据的不同版本,很难将其视为任何提到的 Java 版本中的错误。自 Java 9 以来,CLDR 一直是 Java 中的默认语言环境数据 — 包括不同语言环境中的日期和月份缩写。

演示:使用您的格式化程序,但将其修改为使用 Locale.CANADA,如您所说:

    DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().
            appendPattern("EEE, dd MMM yyyy HH:mm:ss zzz").
            toFormatter(Locale.CANADA);
    System.out.println("Sample: " + ZonedDateTime.now(ZoneId.of("America/Toronto"))
            .format(dateFormatter));

运行 在 Java 10.0.2 上打印没有点:

Sample: Sun, 30 Sep 2018 10:39:28 EDT

在 Java 11 build 11+28:

Sample: Sun., 30 Sep. 2018 10:50:29 EDT

所以我认为该行为与您链接到的错误报告无关。

链接