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 类、SimpleDateFormat
和 Date
早已过时且设计不佳,因此我建议避免使用它们。在 Java 8 及更高版本上,我们当然没有理由使用它们,并且 java.time 也已反向移植到 Java 6 和 7。
链接
我有这段代码:
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 类、SimpleDateFormat
和 Date
早已过时且设计不佳,因此我建议避免使用它们。在 Java 8 及更高版本上,我们当然没有理由使用它们,并且 java.time 也已反向移植到 Java 6 和 7。