【问题标题】:DateTimeParseException on Java 11 but works on Java 10Java 11 上的 DateTimeParseException 但适用于 Java 10
【发布时间】:2018-09-29 21:30:57
【问题描述】:

以下测试用例在 Java 10 下完美运行:

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)

发生了什么事?

更新:将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)

【问题讨论】:

  • 我测试了你的代码using JDK 11 downloaded from Oracle's web site,对我来说效果很好。我使用的是 Windows 10,并下载了 zip 文件而不是 exe 文件。
  • 两个测试是否在同一台计算机上运行? Java 的默认语言环境是什么?你的 Java 10 和你的 Java 11 一样吗?
  • @skomisa 默认区域设置为加拿大。如果您将Locale.CANADA 传递给toFormatter(),您应该会看到问题。
  • @Gili 是的,我现在看到了问题,即使我在 JDK 11 下使用 -source 10 也会出现DateTimeParseException。代码使用 JDK 10 运行良好。

标签: java-time java-11


【解决方案1】:

DateTimeFormatter.RFC_1123_DATE_TIME

您的日期时间字符串采用RFC 822/RFC 1123 格式。不要构建自己的格式化程序,而是使用内置的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);

输出是:

结果:2018-09-29T20:49:02Z

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

你的代码出了什么问题?

在 Java 11 中,Java 期望星期几和月份的缩写在 Locale.CANADASat.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 上运行这不打印任何点:

示例:2018 年 9 月 30 日星期日 10:39:28 EDT

在 Java 11 build 11+28 上:

示例:2018 年 9 月 30 日星期日 10:50:29 EDT

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

链接

【讨论】:

  • 如果我将 toFormatter() 替换为 toFormatter(Locale.CANADA) 并在 Java 10 和 11 下运行,我会看到代码在 Java 10 下运行但在 Java 11 下失败。
  • 我相信您的答案/cmets 包含错字。您编写了 RFC 1134,但在代码中枚举用于 RFC 1123。编号不同。
  • 不止一次,@Gili。已更正。感谢您指出这一点。
  • 只是为了确认使用RFC_1123_DATE_TIME 也为我解决了这个问题。
  • Oracle 得出了同样的结论:bugs.openjdk.java.net/browse/JDK-8211321。谢谢。
猜你喜欢
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 2021-02-14
  • 2019-08-11
  • 2019-08-07
相关资源
最近更新 更多