Java DateTimeFormatter Month Of Year Format



I am trying to convert an Instant to a String with the format like “10 Jul 2021, 10:00 PM”.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd LLL yyyy, hh:mm a");
String formattedDate = formatter.withZone(ZoneId.from(ZoneOffset.UTC)).format(instant);

It works as expected on my machine, but it comes out as “10 7 2021, 10:00 PM” in other environments.

Answer

Use MMM for month abbreviation and specify desired locale

    Instant instant = Instant.ofEpochSecond(1_625_954_400);
    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("dd MMM uuuu, hh:mm a", Locale.US);
    String formattedDate = formatter.withZone(ZoneOffset.UTC).format(instant);
    System.out.println(formattedDate);

Output:

10 Jul 2021, 10:00 PM

This should be stable across computers except that it may theoretically vary with different Java versions. I don’t expect it to.

What went wrong in your code?

By all likelihood the inconsistent results that you have observed are due to different locales. When not instructed otherwise, the one-arg DateTimeFormatter.ofPattern() gives you a formatter that is using the default locale of the JVM (usually taking from an operating system setting). This will give you very varied results on computers and JVMs with different language and region settings. To confuse things further locale data vary with Java version and locale provider setting (the java.locale.providers system property). On my Java 8 very many locales gave 7 as month from LLL and only German have Jul. On my Java 11 only the Vai language of Liberia gives 7 while many give Jul.

Format pattern letter L is for the stand-alone form of month name or abbreviation and should generally not be used when the month is part of a date as it is in your case. In most locales L and M give the same results, but there are locales where there’s a difference and on purpose.



Source: stackoverflow