Java 9+与低版本DateFormat.parse行为差异的无代码修改兼容方案咨询
遗留Java应用Java 9+日期格式化兼容问题解决
我最近碰到一个典型的Java版本兼容性坑:一个用Java 5编译的遗留Web应用,在Java 5到8的环境下跑完全正常,但迁移到Java 12时突然出现日期解析失败的问题,而且因为是遗留系统,根本没法修改源代码。
问题根源
排查后发现是java.text.DateFormat的parse(String)方法在Java 9及以上版本发生了行为变更——同样的日期字符串,在Java 5-8能正常解析的,到Java 9+就抛出ParseException,反过来某些之前解析失败的格式现在又能正常处理了。调整user.country系统属性也没解决问题。
测试验证代码
为了复现问题,我写了一段测试代码:
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()); } } } }
不同版本JVM运行结果对比
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
可行解决方案
因为不能修改应用源代码,只能通过调整JVM参数来兼容。经过测试,在Java命令中添加以下参数即可让Java 11、12的行为和Java 8及以下版本保持一致:
-Djava.locale.providers=COMPAT,CLDR
这个参数指定了Locale服务的提供者顺序,优先使用兼容旧版本的COMPAT实现,再用CLDR,从而恢复了Java 8及之前的日期解析行为。
内容的提问来源于stack exchange,提问作者hairysocks
相关产品推荐
相关产品推荐

