【发布时间】:2018-10-28 21:07:14
【问题描述】:
我在一个legacy应用程序中有代码和一个测试用例,可以总结如下:
@Test
public void testParseDate() throws ParseException {
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
String pattern = "EEE MMM dd HH:mm:ss z Z yyyy";
DateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.GERMANY);
Date date = dateFormatter.parse(toParse);
//skipped assumptions
}
此测试在 Java 8 及更低版本中通过。然而,随着 Java 10 向上,这会导致 java.text.ParseException: Unparseable date: "Mo Aug 18 11:25:26 MESZ +0200 2014"。
记录在案:
除了de_DE,对于语言环境也会抛出异常
de_CH, de_AT, de_LU.
我知道日期格式是changed with JDK 9 (JEP 252)。但是,我认为这是破坏向后兼容性的破坏性更改。摘录:
在 JDK 9 中,Unicode 联盟的通用语言环境数据存储库 (CLDR) 数据被启用为默认语言环境数据,因此您可以使用标准语言环境数据而无需任何进一步的操作。
在 JDK 8 中,虽然 CLDR 语言环境数据与 JRE 捆绑在一起,但默认情况下并未启用。
使用区域设置敏感服务(例如日期、时间和数字格式)的代码可能会与 CLDR 区域设置数据产生不同的结果。
为星期几添加. (Mo.) 可以弥补这一点,测试将通过。但是,对于旧数据(以 XML 等序列化形式),这并不是真正的解决方案。
检查此stackoverflow post,似乎该行为是针对德语区域设置的,可以通过使用COMPAT 模式指定java.locale.providers 来缓解。但是,我不喜欢依赖某些系统属性值的想法,原因可能有两个:
- JDK 下一版本中的更改。
- 在不同的环境中被遗忘。
我的问题是:
- 如何在不重写/修改现有序列化数据或添加/更改系统属性(如
java.locale.providers)的情况下保持遗留代码与此特定日期模式的向后兼容性,这些属性可能会在不同的环境中被遗忘(应用程序服务器, 独立 jars, ...) ?
【问题讨论】:
-
也许有一个丑陋的解决方法:拦截调用并在传递数据之前检查/修改数据?
-
您可以在 Java 中设置系统属性:
System.setProperty("java.locale.providers", "COMPAT,CLDR");。这将防止它在任何环境中被遗忘。当然,它仍然不能保证 Java 11 及更高版本的任何内容。您可能需要考虑一个将所有旧日期时间数据转换为 ISO 8601 的项目(这似乎是面向未来的): -
可以将 EEE 更改为 EE,但这对于其他语言环境可能会变得丑陋。也许你想要一些宽大处理,无论是 Mo 还是 Mon。
-
@JoopEggen
EE MMM dd HH:mm:ss z Z yyyy不起作用。它导致java.text.ParseException: Unparseable date: "Mo Aug 18 11:25:26 MESZ +0200 2014" -
@rzo 我很困惑为什么您遇到兼容性问题但拒绝使用 Oracle 明确提供的 compatibility solution 作为解决方案:
java.locale.providers和COMPAT或 @987654326 @API?
标签: java java-8 simpledateformat java-9 java-10