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.
Advertisement
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.