SimpleDateFormat toPattern在java 9中的行为有所不同

Jep*_*ppz 5 java date date-format simpledateformat java-9

DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("SV", "SE"));
((SimpleDateFormat) dateFormat).toPattern();
Run Code Online (Sandbox Code Playgroud)

在Java 8中,这一行在"yyyy-MM-dd"Java 9中生成"y-MM-dd".

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

Ole*_*.V. 6

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

在我的jdk-9.0.4上运行,打印出来

YYYY-MM-DD

您可能希望-D在命令行上设置属性,它应该没有任何区别.

在Java 9中,Unicode Consortium中的公共区域设置数据存储库(CLDR)用作区域设置数据的默认源,而早期Java版本则不是这种情况.如上所述设置系统属性可启用Java 8行为.正如nullpointer在评论中所说,你可以在这里阅读更多内容:默认情况下使用CLDR Locale Data.

Basil Bourque在他的评论中是正确的,习惯上使用小写缩写语言,所以你应该指定sv以确保你不要混淆你的读者.

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

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

DateTimeFormatterBuilder.getLocalizedDateTimePattern(
        FormatStyle.SHORT, null, IsoChronology.INSTANCE, new Locale("SV", "SE")));
Run Code Online (Sandbox Code Playgroud)

然而,对于一些语言环境(en-CY塞浦路斯例如,英语)的结果不同于DateFormatDateTimeFormatter,所以如果你的目标是最大的向后兼容性,坚持使用过时的DateFormat类.

  • 也许没关系,但我相信各种与语言环境相关的标准在语言代码中使用小写。所以也许那应该是`new Locale(“sv”, “SE”)`? (2认同)
  • `new Locale("SV","SE").equals(new Locale("sv","SE"))`返回`true`,所以我认为它没关系.@BasilBourque (2认同)
  • 注意:属性“ java.locale.providers”仅在Java运行时启动时读取,因此以后对System.setProperty()的调用将无效。(请参见[LocaleServiceProvider API](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/spi/LocaleServiceProvider.html))。因此,在代码中设置此属性(例如@ OleV.V。的给定示例)不是最佳实践,并且可能导致难以发现错误。 (2认同)