我有这段代码:
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()));
}
}
对于 Java 8,输出是:
澳大利亚东部标准时间 2019 年 7 月 16 日星期二 13:16:54
使用 Java 11:
澳大利亚东部时间 2019 年 7 月 16 日星期二 13:16:54
为什么会有差异,我应该如何修改我的代码以使其在两个 Java 版本中均等地工作?
我实际上使用的是 Handlebars在发现这个问题的同时,我可以将它缩小到 Java 版本——但是知道如何使用 Handlebars 为相同的格式字符串产生相同的结果会很酷……)
长话短说
使用系统属性 java.locale.providers
运行 Java 9 及更高版本(包括 Java 11),定义如下:
java -Djava.locale.providers=COMPAT,CLDR YourApp
现在输出没有点,格式与 Java 8 相同,例如:
Tue, 16 Jul 2019 14:24:15 AEST
CLDR
Java 从最多四个来源获取其语言环境数据,包括不同语言中星期几和月份的缩写。直到 Java 8 Java 自己的语言环境数据是默认的。来自 Unicode Common Locale Data Repository(CLDR;见底部链接)的 Java 8 语言环境数据也包括在内,从 Java 9 开始它们是默认值。通过在上述系统属性中指定 COMPAT
,Java 自己的数据仍然包含在内并可访问。我们需要将它放在字符串的第一位,因为源会依次尝试。
人们可能期望另一种(甚至更好的)解决方案是在所有 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。您使用的日期时间类 SimpleDateFormat
和 Date
早已过时且设计不佳,因此我建议避免使用它们。在 Java 8 及更高版本上,我们当然没有理由使用它们,而且 java.time 也已向后移植到 Java 6 和 7。
链接