使用DateTimeFormatter获取本地特定的日期

时间:2019-01-17 14:25:54

标签: java date-format

我一直试图将某些日期转换为特定于语言环境的格式。 可以说我的日期是: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일

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

方法1:

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]

方法2:

        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。

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

2 个答案:

答案 0 :(得分:3)

编辑: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

  

无法在命令行中添加任何其他选项,因为这   应用程序将通过其他系统运行。

很不幸。您可能要再问一次。另一方面,命令行选项可能会改变该其他系统所有部分的行为,因此您可能无法完全避免这种情况。

如果其他所有方法均失败,请为FormatStyle.LONG无法满足您要求的语言环境编写一些例外情况。 The answer by Joop Eggen显示了执行此操作的一种方法。

一旦另一个系统的管理者决定升级到Java 9或更高版本,除非他们使用命令行选项在COMAPT之前使用CLDR,否则语言环境数据将发生变化,然后您将拥有有机会简化您的代码。

答案 1 :(得分:3)

由于您不想以自定义格式列出所有语言环境,因此修补例外似乎更好。可以是自定义模式,也可以只是选择其他样式/后期编辑。

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);
}

补丁以不同的方式修补 ja ko

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