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

Sia*_*noq 4 java simpledateformat java-8 java-11

我有这小段代码:

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()));

    }
}

Run Code Online (Sandbox Code Playgroud)

使用Java 8,输出为:

Tue, 16 Jul 2019 13:16:54 AEST

使用Java 11:

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

为什么会有区别?我该如何修改代码以使其在两个Java版本中均能正常工作?

我实际上是在发现此问题时使用的是Handlebars,可以将其范围缩小到Java版本-但是知道如何使用Handlebars为相同的格式字符串产生相同的结果会很酷。

Ole*_*.V. 9

TL; DR

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

java -Djava.locale.providers=COMPAT,CLDR YourApp
Run Code Online (Sandbox Code Playgroud)

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

周二,2019年7月16日14:24:15 AEST

CLDR

Java从多达四个来源获取其语言环境数据,包括一周中的几天和几个月以不同语言使用的缩写。最多Java 8 Java自己的语言环境数据是默认设置。在Java 8中,还包括Unicode Common Locale Data Repository(CLDR;请参阅底部的链接)中的数据,而从Java 9中,它们是默认值。通过COMPAT在上述系统属性中进行指定,仍然可以包含和访问Java自己的数据。我们需要将其放在字符串的开头,因为依次尝试了源。

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

在Java 8上:

周二,2019年7月16日14:35:02 AEST

在Java 9和11上:

2019年7月16日,星期二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));
Run Code Online (Sandbox Code Playgroud)

我正在使用并推荐使用java.time(现代Java日期和时间API)。您使用的日期时间类SimpleDateFormatDate早已过时,并且设计总是很差,所以我建议避免使用它们。在Java 8及更高版本上,当然没有理由使用它们,而且java.time也已反向移植到Java 6和7。

链接

  • 非常感谢您详尽的解释 - 我很感谢您花时间给出答案。这就是我访问(并发布到)stackoverflow 的原因!+1 为你有趣的标题 (tl;dr / cldr) :D (2认同)