使用 DateTimeFormatter 获取本地特定日期

Get local specific Date using DateTimeFormatter

我一直在尝试将一些日期转换为特定于语言环境的格式。 比如我有日期:2019 年 1 月 17 日

我想为以下语言环境翻译此日期:

localized time for en-GB: 17 January 2019
localized time for es-ES: 17 de enero de 2019 
localized time for zh-CN: 2019年1月17日 
localized time for de-DE: 17. Januar 2019 
localized time for fr-FR: 17 janvier 2019 
localized time for it-IT: 17 gennaio 2019 
localized time for ja-JP: 2019年1月17日 
localized time for ko-KR: 2019년 1월 17일

我尝试了多种方法来实现这一点:

方法一:

final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM,
                Locale.forLanguageTag(locale)));

不同语言环境的输出:

localized time for en-GB: 17 January 2019
localized time for es-ES: 17 de enero de 2019 
localized time for zh-CN: 2019年1月17日 
localized time for de-DE: 17. Januar 2019 
localized time for fr-FR: 17 janvier 2019 
localized time for it-IT: 17 gennaio 2019 
localized time for ja-JP: 2019/01/17 [Getting the date in numerical form]
localized time for ko-KR: 2019년 1월 17일 (목) [Getting this extra character at the end for ko-KR]

方法二:

        ZonedDateTime zoned = ZonedDateTime.now();
    DateTimeFormatter pattern = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.forLanguageTag(locale));

不同语言环境的输出:

zoned fek long ja-JP:  2019年1月17日                                                                                                    
zoned fek long ko-KR:  2019년 1월 17일 목요일                                                                                           
zoned fek long es-ES:  jueves 17 de enero de 2019                                                                                       
zoned fek long fr-FR:  jeudi 17 janvier 2019                                                                                            
zoned fek long it-IT:  giovedì 17 gennaio 2019                                                                                          
zoned fek long de-DE:  Donnerstag, 17. Januar 2019                                                                                      
zoned fek long ko-KR:  jeudi 17 janvier 2019

在这种方法中,JP 看起来不错,但所有其他语言环境在输出中也有 Day。

我必须显示上面提到的日期。

编辑:CLDR

运行 使用命令行选项 -Djava.locale.providers=CLDR,COMPAT 的方法 2。例如:

java -Djava.locale.providers=CLDR,COMPAT YourApp

输出:

zoned fek long en-GB: 17 January 2019
zoned fek long es-ES: 17 de enero de 2019
zoned fek long zh-CN: 2019年1月17日
zoned fek long de-DE: 17. Januar 2019
zoned fek long fr-FR: 17 janvier 2019
zoned fek long it-IT: 17 gennaio 2019
zoned fek long ja-JP: 2019年1月17日
zoned fek long ko-KR: 2019년 1월 17일

我发现在我的 Java 9 上无法重现您的问题。使用 FormatStyle.LONG 我得到了 2019年1月17日 的日语,而你报告 2019/01/17。 Java 从不同来源获取日期格式作为其语言环境数据的一部分。来自Java 来自Unicode Common Locale Data Repository (CLDR) 的 8 个语言环境数据来自 Java,但 Java 自己的语言环境数据被用作默认值。从 Java 9 开始,相反,CLDR 数据被用作默认值。所以我对上面的命令行选项所做的是告诉你的 Java 8 在 Java 自己的之前使用 CLDR。 Java 自己的语言环境数据指定为 COMPAT。

另一个选择当然是升级到 Java 9、10 或 11。这也会给你你想要的结果。

Java 8 没有命令行选项

Can not add any additional option in the command line since this application will run th[r]ough a different system.

真不幸。你可能想再问一次。另一方面,命令行选项可能会改变其他系统所有部分的行为,因此您可能无法通过这种方式。

如果其他所有方法都失败了,请为 FormatStyle.LONG 未提供所需内容的语言环境编写一些例外代码。 展示了一种方法。

一旦该其他系统的管理员决定升级到 Java 9 或更高版本,除非他们使用命令行选项在 CLDR 之前使用 COMAPT,否则区域设置数据将会更改然后您将有机会简化您的代码。

由于您不想以自定义格式列出所有语言环境,因此修补例外情况似乎更好。这可能是自定义模式,或者只是选择另一种样式/post-编辑。

String[] locales = {"en-GB", "es-ES", "zh-CN", "de-DE", "fr-FR", "it-IT",
    "ja-JP", "ko-KR", "ko-KP"};
for (String loc : locales) {
    String[] langCtry = loc.split("-");
    Locale locale = new Locale(langCtry[0], langCtry[1]);
    Locale.setDefault(locale);
    LocalDate.set(2019, 1, 17);
    FormatStyle style = locale.getLanguage().equals("ja") ? FormatStyle.FULL 
                                                          : FormatStyle.LONG;
    DateTimeFormatter.ofLocalizedDate(style);
    String text = format.format(date);
    if (locale.getLanguage().equals("ko")) {
        text = text.replaceFirst("\s\S+$", "");
    }
    System.out.printf("%s: %s%n", locale, text);
}

这个 补丁 jako,以不同的方式。

用于检查预期的单元测试套件可能会有用,因为特定于区域设置的数据可能会随时间变化。