SimpleDateFormat .format() 在 Java8 和 Java11 中给出不同的结果

SimpleDateFormat .format() gives different results in Java8 vs. Java11

我有这段代码:

import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");

        System.out.println(format.format(new Date()));

    }
}

加上Java8,输出为:

Tue, 16 Jul 2019 13:16:54 AEST

与Java11:

Tue., 16 Jul. 2019 13:16:54 AEST

为什么会有差异,我应该如何修改我的代码以使其在两个 Java 版本中均等地工作?

我在发现这个问题时实际上是在使用 Handlebars,我可以将其缩小到 Java 版本 - 但如果知道如何使用 Handlebars 来产生相同的结果会很酷对于相同的格式字符串...)

TL;DR

运行 您的 Java 9 及更高版本(包括 Java 11)与系统 属性 java.locale.providers 定义如下:

java -Djava.locale.providers=COMPAT,CLDR YourApp

现在输出没有点,格式与 Java 8 相同,例如:

Tue, 16 Jul 2019 14:24:15 AEST

CLDR

Java 从最多四个来源获取其语言环境数据,包括不同语言中星期几和月份的缩写。最多 Java 8 Java 自己的语言环境数据是默认的。来自 Java 8 来自 Unicode 通用语言环境数据存储库(CLDR;见底部链接)的语言环境数据也包括在内,从 Java 9 它们是默认值。 Java自己的数据仍然包含在上面的系统属性中,通过指定COMPAT可以访问。我们需要把它放在字符串的第一位,因为源会依次尝试。

人们可能期望另一种(甚至更好的)解决方案是在所有 Java 版本中使用 CLDR。奇怪的是,在这种情况下,这并没有在所有 Java 版本上为我们提供相同的格式。这是将 属性 设置为 CLDR,JRE 时的输出(JRE 是 COMPAT 的旧名称,在 Java 8 上我们需要改用它)。

在 Java 8:

Tue, 16 Jul 2019 14:35:02 AEST

在 Java 9 和 11:

Tue., 16 Jul. 2019 14:35:52 AEST

CLDR 有多个版本,不同的 Java 版本包含不同的版本。

java.time

这是我用于上述输出的片段。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.forLanguageTag("en-AU"));
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
    System.out.println(now.format(formatter));

我正在使用并推荐 java.time,现代 Java 日期和时间 API。您使用的 date-time 类、SimpleDateFormatDate 早已过时且设计不佳,因此我建议避免使用它们。在 Java 8 及更高版本上,我们当然没有理由使用它们,并且 java.time 也已反向移植到 Java 6 和 7。

链接