DateFormat 日期解析行为从 Java 8 更改为 Java 9,是否有相关的环境设置?

hai*_*cks 6 java parsing date unparseable

我有一个遗留的 Web 应用程序,其中的 Java 代码是在 Java 5 中编译和运行的,当尝试构建新环境以在 Java 12 中运行相同的代码时,我遇到了日期格式问题。我已经在 J​​ava 5、7、8、9、10、11、12 中对此进行了测试,并且使用 Java 9 或更高版本时代码行为会发生变化。

我无法更改 Web 应用程序的 Java 源代码。

问题与使用 java.text.DateFormat 和 parse(String) 方法有关。

这个小测试应用程序显示了这个问题:

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());
            }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

我用 Java 5 编译了代码,并在不同版本上运行相同的类。

在 Java 5 到 8 中运行此命令,输出如下:

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"
Run Code Online (Sandbox Code Playgroud)

在 Java 9 或更高版本中运行,输出如下:

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
Run Code Online (Sandbox Code Playgroud)

DateFormat 解析方法的默认行为的这种更改会导致我的 Web 应用程序出现错误。

有没有人见过这个,并弄清楚如何让默认值在不同的 Java 版本中保持一致?

我想知道这是否与操作系统环境变量传递到 Java 系统属性有关。我最接近的改变是更改“user.country”Java 属性。但我找不到可以给出从 DD-MMM-YYYY 格式解析的日期的设置。

请记住 - 我无法更改 java 源代码 - 我只能修改操作系统环境属性和 Java 系统属性。


解决方案

通过下面的答案提供,其中给出了相关文章。

我已经在 J​​ava 11 和 12 上对此进行了测试,并且它有效。将以下命令行选项添加到 java 命令:

-Djava.locale.providers=COMPAT,CLDR
Run Code Online (Sandbox Code Playgroud)

使用该命令行选项在 Java 11 或 12 中运行测试应用程序将提供与在不使用命令行选项的情况下使用 Java 8 或更低版本运行相同的输出。

Bas*_*que 4

是的,Java 9 中的情况发生了变化。这就是为什么您应该在升级任何软件之前研究发行说明的示例。

在 Java 9 及更高版本中,OpenJDK 默认使用不同的本地化数据源:Unicode 联盟提供的CLDR 。参见JEP 252

CLDR 是此类信息的丰富的来源。但正如您所看到的,本地化是一个不断发展的人类语言和文化规范的复杂问题,因此对于正确性的看法可能存在差异,并且随着时间的推移可能会发生变化。

您的问题中的解决方法是正确的:使用早期版本的 Java 中的旧默认值覆盖本地化数据的新默认源。