JDK-8329375 : English date format MMM does not always yield 3 letter month
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 22
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2024-03-30
  • Updated: 2024-09-07
  • Resolved: 2024-04-01
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
Tested Windows 10 with Oracle JDK22, OpenJDK22, OpenJDK17

A DESCRIPTION OF THE PROBLEM :
Most documentation suggests that date format MMM is a 3 letter version of the month. This is not the case in English :- JDK returns 11 of the months as 3 characters, but September as 4 letters: "Sept". I cannot imagine why English MMM uses "Sept" for September. This makes exchanging dates in applications unreliable - reading and formatting dates with month abbreviation needs to pre-process text by String.replace("Sept","Sep") one way or the other.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run attached code example. Output will show MMM month format for UK and US and tries to parse a date in format "dd MMM yyyy"

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
There should not be any exception and it should print "MMM#9 UK=Sep US=Sep"
MMM#1 UK=Jan US=Jan
MMM#2 UK=Feb US=Feb
MMM#3 UK=Mar US=Mar
MMM#4 UK=Apr US=Apr
MMM#5 UK=May US=May
MMM#6 UK=Jun US=Jun
MMM#7 UK=Jul US=Jul
MMM#8 UK=Aug US=Aug
MMM#9 UK=Sep US=Sep
MMM#10 UK=Oct US=Oct
MMM#11 UK=Nov US=Nov
MMM#12 UK=Dec US=Dec
str1=20 Sept 23
str2=20 Sep 23
dt2=2023-09-20
dt1=2023-09-20

ACTUAL -
MMM#1 UK=Jan US=Jan
MMM#2 UK=Feb US=Feb
MMM#3 UK=Mar US=Mar
MMM#4 UK=Apr US=Apr
MMM#5 UK=May US=May
MMM#6 UK=Jun US=Jun
MMM#7 UK=Jul US=Jul
MMM#8 UK=Aug US=Aug
MMM#9 UK=Sept US=Sep
MMM#10 UK=Oct US=Oct
MMM#11 UK=Nov US=Nov
MMM#12 UK=Dec US=Dec
str1=20 Sept 23
str2=20 Sep 23
dt2=2023-09-20
Exception in thread "main" java.time.format.DateTimeParseException: Text '20 Sep 23' could not be parsed at index 3
        at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2108)
        at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2010)
        at java.base/java.time.LocalDate.parse(LocalDate.java:435)
        at DateProblem.main(DateProblem.java:52)

---------- BEGIN SOURCE ----------
/**
 * UK date formats with MMM are 3 letters long for all months except September 
 */
public class DateProblem
{
    public static void main(String... args)
    {
        final ZoneId gmt = ZoneId.of("GMT");

        final DateTimeFormatter fmtMMM = DateTimeFormatter.ofPattern("MMM").withZone(gmt);
        final DateTimeFormatter fmtMMM1 = fmtMMM.withLocale(Locale.UK);
        final DateTimeFormatter fmtMMM2 = fmtMMM.withLocale(Locale.US);

        // For me: Locale.getDefault().equals(Locale.UK) is true
        // System.out.println("UK? "+Locale.getDefault().equals(Locale.UK));

        for (int i = 1; i <= 12 ; i++)
        {
            LocalDate d = LocalDate.of(2024, i, 28);
            System.out.println("MMM#"+i+" UK="+fmtMMM1.format(d)+" US="+fmtMMM2.format(d));
        }

        // Note: RFC_1123_DATE_TIME does use "Sep"
//        DateTimeFormatter rfc1123 = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.UK);
//        for (int i = 1; i <= 12 ; i++)
//        {
//            ZonedDateTime dt = LocalDateTime.of(2024, i, 28, 12, 34, 56).atZone(gmt);
//            System.out.println("RFC_1123_DATE_TIME#"+i+" is "+rfc1123.format(dt));
//        }

        DateTimeFormatter ddMMMyyyy = DateTimeFormatter.ofPattern("dd MMM yy").withZone(gmt);
        DateTimeFormatter ddMMMyyyy1 = ddMMMyyyy.withLocale(Locale.UK);
        DateTimeFormatter ddMMMyyyy2 = ddMMMyyyy.withLocale(Locale.US);

        final LocalDate dtSep20th2023 = LocalDate.of(2023,9,20);
        final String strSep20th2023  = "20 Sep 23";

        String str1 = ddMMMyyyy1.format(dtSep20th2023);
        System.out.println("str1="+str1);
        String str2 = ddMMMyyyy2.format(dtSep20th2023);
        System.out.println("str2="+str2);

        LocalDate dt2 = LocalDate.parse(strSep20th2023, ddMMMyyyy2);
        System.out.println("dt2="+dt2);
        LocalDate dt1 = LocalDate.parse(strSep20th2023, ddMMMyyyy1);
        System.out.println("dt1="+dt1);
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Dates in string format have to undergo String replacement .replace("Sept","Sep")  or .replace("Sep","Sept").

FREQUENCY : always



Comments
As mentioned in JDK-8293917: JDK is a downstream user of CLDR (Common Locale Data Repository, run by Unicode Consortium), and the change was done in the upstream CLDR: https://unicode-org.github.io/cldr-staging/charts/38/delta/en.html#Months%20-%20abbreviated%20-%20Standalone If the reporter still has questions. Please file a bug report against CLDR with a rationale to revert that "Sept" change. Closed as a duplicate of JDK-8293917.
07-09-2024

Additional Information from submitter: ================================ This clearly was a terrible decision by Unicode consortium which affects CLDR 38 onwards and therefore breaks JDK16 through at least JDK22 (CLDR 44). There are reports that .NET users have similar problems. Unfortunately Java code for some users will break once upgrading past JDK16. Looking at this thread it does not sound like a fix will be forthcoming soon - see https://unicode-org.atlassian.net/browse/CLDR-14412 A better workaround is to hardcode use of ENGLISH locale or switch off the regional aspect of the current locale. For example these work in JDK16-22: DateTimeFormatter.ofPattern("dd MMM yyyy").withLocale(Locale.of(Locale.getDefault().getLanguage())).parse("12 Sep 2023"); DateTimeFormatter.ofPattern("dd MMM yyyy").withLocale(Locale.ENGLISH).parse("12 Sep 2023");
08-04-2024

> Most documentation suggests that date format MMM is a 3 letter version of the month This is a wrong assumption. The specs for SimpleDateFormat/DateTimeFormatterBuilder intentionally do not mention the number of letters involved, but just designate short/abbreviated form. This is exactly for allowing the cases described in the problem description.
03-04-2024