SimpleDateFormat toPattern 在 java 9 中表现不同

SimpleDateFormat toPattern behaves differently in java 9

DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("SV", "SE"));
((SimpleDateFormat) dateFormat).toPattern();

在 Java 8 中,此行生成 "yyyy-MM-dd",而在 Java 9 中,它生成 "y-MM-dd".

这对我们的遗留代码有一些严重的问题,有什么方法可以恢复这种行为吗?

    System.setProperty("java.locale.providers", "COMPAT,CLDR");
    DateFormat dateFormat
            = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("sv", "SE"));
    System.out.println(((SimpleDateFormat) dateFormat).toPattern());

运行 在我的 jdk-9.0.4 上打印

yyyy-MM-dd

您可能想在命令行上将 属性 设置为 -D,应该没有任何区别。

在 Java9 中,Unicode 联盟的通用语言环境数据存储库 (CLDR) 被用作语言环境数据的默认来源,而在早期的 Java 版本中并非如此。如上所述设置系统 属性 启用 Java 8 行为。正如 nullpointer 在评论中所说,你可以多读一点 here: Use CLDR Locale Data by Default.

Basil Bourque 在他的评论中是正确的,习惯上使用小写的语言缩写,因此您可能应该指定 sv 以确保您不会混淆您的 reader。

人们可能还想知道模式中是一个 y 还是四个是否有什么区别。我阅读 SimpleDateFormat 文档的方式是,y 将根据 80-20 规则解释两位数的年份:它在过去 80 年内或接下来的 20 年内。yyyy会将两位数的年份解释为公元一世纪的年份。假设您的年份在 4 位数范围内(1000 到 9999),不过我认为这不会成为问题。

如果这仅适用于瑞典语言环境,则代码的现代版本会给出相同的结果:

DateTimeFormatterBuilder.getLocalizedDateTimePattern(
        FormatStyle.SHORT, null, IsoChronology.INSTANCE, new Locale("SV", "SE")));

但是,对于许多语言环境(例如 en-CY、塞浦路斯英语),结果在 DateFormatDateTimeFormatter 之间有所不同,因此如果您的目标是最大的向后兼容性,坚持过时的 DateFormat class.