Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SimpleDateFormat toPattern behaves differently in java 9

DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("SV", "SE"));
((SimpleDateFormat) dateFormat).toPattern();

In Java 8 this line produces "yyyy-MM-dd" while in Java 9 it produces "y-MM-dd".

This has some serious issues for our legacy code, is there some way to revert the behaviour?

like image 424
Jeppz Avatar asked Feb 16 '18 15:02

Jeppz


People also ask

What is the difference between DateFormat and SimpleDateFormat?

The java SimpleDateFormat allows construction of arbitrary non-localized formats. The java DateFormat allows construction of three localized formats each for dates and times, via its factory methods.

What can I use instead of SimpleDateFormat?

DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.

What is the use of SimpleDateFormat in Java?

SimpleDateFormat is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for formatting (date -> text), parsing (text -> date), and normalization. SimpleDateFormat allows you to start by choosing any user-defined patterns for date-time formatting.

What does SimpleDateFormat return?

Return Value: The method returns Date or time in string format of mm/dd/yyyy.


1 Answers

    System.setProperty("java.locale.providers", "COMPAT,CLDR");
    DateFormat dateFormat
            = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("sv", "SE"));
    System.out.println(((SimpleDateFormat) dateFormat).toPattern());

Running on my jdk-9.0.4 this prints

yyyy-MM-dd

You may want to set the property with -D on the command line instead, it shouldn’t make any difference.

In Java 9 the Common Locale Data Repository (CLDR) from the Unicode Consortium is used as the default source of locale data, which wasn’t the case in earlier Java versions. Setting the system property as above enables the Java 8 behaviour. As nullpointer said in a comment, you can read a bit more here: Use CLDR Locale Data by Default.

Basil Bourque is correct in his comment, it is customary to use lowercase abbrevation for language, so you should probably specify sv to make sure you don’t confuse your reader.

One might also wonder whether it makes any difference whether there’s one y or four in the pattern. The way I read the SimpleDateFormat documentation, one y will interpret a 2-digit year according to the 80-20 rule: it’s within the last 80 years or within the next 20. yyyy will interpret a 2-digit year as a year in the first century AD. Assuming your years are in the 4-digit range (1000 through 9999), I wouldn’t expect it to be a problem, though.

If this was only for Swedish locale, the modern version of the code would give the same result:

DateTimeFormatterBuilder.getLocalizedDateTimePattern(
        FormatStyle.SHORT, null, IsoChronology.INSTANCE, new Locale("SV", "SE")));

However, for a number of locales (en-CY, Cyprus English, for example) the result differs from DateFormat to DateTimeFormatter, so if your goal was maximal backward compatibility, stick with the outmoded DateFormat class.

like image 156
Ole V.V. Avatar answered Oct 18 '22 16:10

Ole V.V.