Search code examples
javadatedatetime-formatjava-timejava-16

SimpleDateFormat - format - Month September - JDK16


I have just upgraded Java from JDK-15 to JDK-16 and I see a problem while converting Date using SimpleDateFormat. September month alone while formatted using yyyy-MMM-dd is giving 4 characters instead of 3.

Eg: 2021-Sep-11 is being shown as 2021-Sept-11

    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.DATE, 150);
    SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MMM-dd");
    System.out.println(cal.getTime());

    String formatted = format1.format(cal.getTime());
    System.out.println(formatted);

Looks like a bug to me. I can't see any update to this in the release notes. Anyone facing similar issue? Was working alright till JDK-15.


Solution

  • Never use Date-Time formatting/parsing type without Locale because the texts are Locale-sensitive.

    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, 150);
            SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MMM-dd", Locale.ENGLISH);
            System.out.println(cal.getTime());
    
            String formatted = format1.format(cal.getTime());
            System.out.println(formatted);
        }
    }
    

    Output:

    2021-Sep-11
    

    Note that the java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API* .

    Using modern date-time API:

    import java.time.LocalDate;
    import java.time.ZoneId;
    import java.time.format.DateTimeFormatter;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            // Change ZoneId as per your requirement e.g. ZoneId.of("Europe/London")
            LocalDate date = LocalDate.now(ZoneId.systemDefault());
            date = date.plusDays(150);
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MMM-dd", Locale.ENGLISH);
            String formatted = dtf.format(date);
            System.out.println(formatted);
        }
    }
    

    Output:

    2021-Sep-11
    

    Check this answer to learn more about u vs y.

    Learn more about the modern date-time API from Trail: Date Time.


    * For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.