【问题标题】:SimpleDateFormat toPattern behaves differently in java 9SimpleDateFormat toPattern 在 java 9 中的行为不同
【发布时间】:2018-07-27 12:41:01
【问题描述】:
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("SV", "SE"));
((SimpleDateFormat) dateFormat).toPattern();

在 Java 8 中,这一行产生 "yyyy-MM-dd",而在 Java 9 中,它产生 "y-MM-dd"

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

【问题讨论】:

  • @ΦXocę웃Пepeúpaツ 好的,它在 intellij 评估表达式中工作,但不强制转换就无法编译,更新了我的示例。
  • 可能是因为CLDR date time patterns?迁移指南的要点是 如果您的应用程序成功启动,请仔细查看您的测试并确保其行为与 JDK 8 上的相同。例如,一些早期采用者注意到他们的日期和货币格式不同.请参阅默认使用 CLDR 区域设置数据。
  • 如果您需要字符串"yyyy-MM-dd",只需使用字符串"yyyy-MM-dd"。如果您向工厂询问区域设置和样式的模式,您接受这是一个移动目标。我怀疑瑞典是否愿意仅仅为了一些遗留的 Java 代码而确定他们的日期格式……
  • 在使用 Java 9 时,您到底为什么还在使用早已过时且臭名昭著的麻烦 SimpleDateFormat?如果您现在不想将其从遗留代码中删除,我可以理解,但对于手头的任务,请使用DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT, null, IsoChronology.INSTANCE, new Locale("SV", "SE"))(但这并不能解决您的问题,它在 Java 8 和 9 中的行为也不同)。
  • @Jeppz 您查询的语言环境并不重要,它们都不能保证永远不会更改属性。

标签: java date simpledateformat date-format java-9


【解决方案1】:
    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 设置属性,这应该没有任何区别。

在 Java 9 中,来自 Unicode Consortium 的 Common Locale Data Repository (CLDR) 被用作默认的语言环境数据源,而在早期的 Java 版本中并非如此。如上所述设置系统属性会启用 Java 8 行为。正如nullpointer在评论中所说,您可以阅读更多here: Use CLDR Locale Data by Default

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

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

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

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

但是,对于许多语言环境(例如en-CY,塞浦路斯英语),结果从 DateFormatDateTimeFormatter 不同,因此如果您的目标是最大程度地向后兼容,请坚持使用过时的 DateFormat 类.

【讨论】:

  • 也许没关系,但我相信各种与语言环境相关的标准在语言代码中使用小写。所以也许应该是new Locale( “sv” , “SE” )
  • 我也是这么想的,@BasilBourque,但从问题中逐字逐句获取了语言环境。我已经运行了代码,它可以工作。
  • new Locale("SV", "SE").equals(new Locale("sv", "SE")) 返回true,所以我认为没关系。 @BasilBourque
  • 另见CLDR和新SimpleDateFormat关于“y”含义的冲突(摇头)。
  • 警告:属性“java.locale.providers”仅在Java运行时启动时读取,因此稍后对System.setProperty()的调用将不起作用。 (见LocaleServiceProvider API)。因此,在代码中设置此属性(如@OleV.V. 给出的示例)不是最佳实践,可能会导致难以发现错误。
猜你喜欢
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多