DateFormat parse of dates changed behaviour from Java 8 to Java 9, are there any relevant environment settings? [duplicate]
Asked Answered
P

1

6

I have a legacy web application with Java code compiled and running in Java 5, when trying to build a new environment to run the same code in Java 12 I came across a date formatting problem. I've tested this in Java 5, 7, 8, 9, 10, 11, 12 and the code behaviour changes when using Java 9 or above.

I don't have the option of changing the Java source code of the web application.

The problem is to do with using java.text.DateFormat and the parse(String) method.

This little test application shows the problem:

import java.util.*;
import java.text.*;

public class LocaleAndDateTester {

    public LocaleAndDateTester() {
    }

    public static final void main(String[] argv) {
        LocaleAndDateTester a = new LocaleAndDateTester();
        a.go();
    }

    private void go() {
        System.out.println("Locale country: " + Locale.getDefault().getDisplayCountry());

        java.text.DateFormat df = java.text.DateFormat.getDateInstance();
        String[] dateToTest = {"01-JAN-2020", "12-SEP-2019", "12/SEP/2019", "12/09/2019",
                               "September 12, 2019", "Sep 12, 2019", "12 Sep 2019",
                               "12 September 2019"};
        System.out.println("\nTesting dates:");
        for (int i = 0; i < dateToTest.length; i++) {
            try {
                Date date = df.parse(dateToTest[i]);
                System.out.println(dateToTest[i] + " -> " + date);
            } catch (ParseException e) {
                System.out.println(e.toString());
            }
        }
    }
}

I compiled the code in Java 5, and ran the same class on different versions.

Running this in Java 5 to 8, the output this this:

Locale country: United Kingdom

Testing dates:
01-JAN-2020 -> Wed Jan 01 00:00:00 GMT 2020
12-SEP-2019 -> Thu Sep 12 00:00:00 BST 2019
java.text.ParseException: Unparseable date: "12/SEP/2019"
java.text.ParseException: Unparseable date: "12/09/2019"
java.text.ParseException: Unparseable date: "September 12, 2019"
java.text.ParseException: Unparseable date: "Sep 12, 2019"
java.text.ParseException: Unparseable date: "12 Sep 2019"
java.text.ParseException: Unparseable date: "12 September 2019"

Running in Java 9 or above, the output is this:

Locale country: United Kingdom

Testing dates:
java.text.ParseException: Unparseable date: "01-JAN-2020"
java.text.ParseException: Unparseable date: "12-SEP-2019"
java.text.ParseException: Unparseable date: "12/SEP/2019"
java.text.ParseException: Unparseable date: "12/09/2019"
java.text.ParseException: Unparseable date: "September 12, 2019"
java.text.ParseException: Unparseable date: "Sep 12, 2019"
12 Sep 2019 -> Thu Sep 12 00:00:00 GMT 2019
12 September 2019 -> Thu Sep 12 00:00:00 GMT 2019

This change of default behaviour of the DateFormat parse method causes errors in my web application.

Has anyone seen this, and worked out how to get the default to remain consistent through different Java versions?

I wondered if it was to do with OS environment variables getting passed into Java System Properties. The closest I got to that causing a change was in changing the "user.country" Java property. But I couldn't find a setting that would give dates parsed from DD-MMM-YYYY format.

Remember - I cannot change java source code - I can only modify OS environment properties and Java System Properties.


SOLUTION

Provided through an answer below, which gives a related article.

I've tested this on Java 11 and 12, and it works. Add the following command-line option to the java command:

-Djava.locale.providers=COMPAT,CLDR

Running the test application in Java 11 or 12 with that command-line option will give the same output as running with Java 8 or lower, without the command-line option.

Planospore answered 19/9, 2019 at 12:16 Comment(3)
Have a look at this question, it is probably related : #48830079 .Tourcoing
Thanks @Tourcoing - that article suggests using "-Djava.locale.providers=COMPAT,CLDR" and that indeed makes thtest application give the same output.Planospore
As an aside an application the source code of which cannot be changed sounds weird to me. It’s the first time I’ve heard of an application where the requirements don’t evolve over so many years (except for the requirement to run on a newer Java version).Trim
F
4

Yes, things changed in Java 9. This is an example why you should study the release notes before upgrading any software.

In Java 9 and later, OpenJDK defaults to a different source of localization data: CLDR provided by the Unicode Consortium. See JEP 252.

The CLDR is a much richer source of this information. But as you have seen, localization is a complicated matter of ever-evolving human languages and cultural norms, so there may be differences of opinion of correctness, and there may be changes over time.

The workaround in your Question is correct: Override the new default source of localization data, using the old default from earlier versions of Java.

Flour answered 19/9, 2019 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.