4

我有一个旧版 Web 应用程序,其中包含在 Java 5 中编译和运行的 Java 代码,当尝试构建一个新环境以在 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());
            }
        }
    }
}

我在 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"

在 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

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

有没有人看到这一点,并想出如何通过不同的 Java 版本让默认值保持一致?

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

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


解决方案

通过下面的答案提供,该答案提供了相关文章。

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

-Djava.locale.providers=COMPAT,CLDR

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

4

1 回答 1

2

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

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

CLDR 是此信息的丰富的来源。但正如您所见,本地化是一个复杂的问题,涉及不断演变的人类语言和文化规范,因此可能存在正确性意见分歧,并且可能会随着时间的推移而发生变化。

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

于 2019-09-19T16:12:19.433 回答