SimpleDateFormat .format() gives different results in Java8 vs. Java11

Siaynoq :

I'm having this little piece of code:

import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");

        System.out.println(format.format(new Date()));

    }
}

With Java 8, the output is:

Tue, 16 Jul 2019 13:16:54 AEST

With Java 11:

Tue., 16 Jul. 2019 13:16:54 AEST

Why is there a difference and how should I modify my code to make it work evenly in both Java versions?

I was actually using Handlebars while finding this issue, and I could narrow it down to the Java version - but it would be cool to know how to use Handlebars to produce the same result for the same format string...)

Ole V.V. :

TL;DR

Run your Java 9 and later (including Java 11) with the system property java.locale.providers defined like this:

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

Now output is without the dots, in the same format as on Java 8, for example:

Tue, 16 Jul 2019 14:24:15 AEST

CLDR

Java gets its locale data, including abbreviations used for days of the week and for months in different languages, from up to four sources. Up to Java 8 Java’s own locale data were the default. From Java 8 locale data from Unicode Common Locale Data Repository (CLDR; see links at the bottom) are included too, and from Java 9 they are the default. Java’s own data are still included and accessible by specifying COMPAT in the above system property. We need to put it first in the string as the sources are tried in turn.

One might have expected that another (and perhaps even a nicer) solution would be to use CLDR in all Java versions. Curiously this doesn’t give us the same format on all Java versions in this case. Here is the output when setting the property to CLDR,JRE (JRE is the old name for COMPAT, on Java 8 we need to use this instead).

On Java 8:

Tue, 16 Jul 2019 14:35:02 AEST

On Java 9 and 11:

Tue., 16 Jul. 2019 14:35:52 AEST

CLDR comes in versions, and not the same version is included with the different Java versions.

java.time

Here’s the snippet I have used for the above outputs.

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.forLanguageTag("en-AU"));
    ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
    System.out.println(now.format(formatter));

I am using and recommending java.time, the modern Java date and time API. The date-time classes that you used, SimpleDateFormat and Date, are long outdated and were always poorly designed, so I recommend avoiding them. On Java 8 and later there’s certainly no reason why we should use them, and java.time has been backported to Java 6 and 7 too.

Links

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=125227&siteId=1