Search code examples
javadate-format

Get local specific Date using DateTimeFormatter


I have been trying to convert some date into locale specific format. For say I have the date : 17 January 2019

I want to translate this date for below locales:

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일

I tried multiple ways to achieve this:

Approach 1:

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

Output for different locales:

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]

Approach 2:

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

Output for different locales:

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

In this approach JP looks fine but all other locales had also Day in the output.

I have to show the dates as it is mentioned in the above.


Solution

  • Edit: CLDR

    Run your approach 2 with the command line option -Djava.locale.providers=CLDR,COMPAT. For example:

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

    Output:

    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일
    

    I discovered that on my Java 9 I could not reproduce your problem. With FormatStyle.LONG I got 2019年1月17日 for Japanese where you reported 2019/01/17. Java gets the date formats as part of its locale data from different sources. From Java 8 locale data from Unicode Common Locale Data Repository (CLDR) come with Java, but Java’s own locale data are used as default. From Java 9 it’s the other way around, CLDR data are used as default. So what I do with the above command line option is I tell your Java 8 to use CLDR before Java’s own. Java’s own locale data are specified as COMPAT.

    The other option of course is to upgrade to Java 9, 10 or 11. This too will give you the result you asked for.

    Java 8 without command line option

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

    That’s unfortunate. You may want to ask once more. On the other hand, the command line option risks changing behaviour in all parts of that other system, so you may not get through that way.

    If all else fails, code some exceptions for the locales where the FormatStyle.LONG doesn’t give you what is required. The answer by Joop Eggen shows one way of doing this.

    Once the managers of that other system decide to upgrade to Java 9 or later, unless they use a command line option to use COMAPT before CLDR, locale data will change and you will then have the opportunity to simplify your code.