不同系统下Java SimpleDateFormat日期解析行为差异问题咨询
问题根因
- 该问题和JDK版本存在一定关联,但核心触发点是**
SimpleDateFormat对区域配置(Locale)的强依赖性**:如果构造时没有显式指定Locale,会自动读取当前JVM的默认Locale,不同贡献者的操作系统语言配置、JVM启动参数不同,默认Locale可能存在差异,不同Locale对MMM(月份格式)、EEE(星期格式)的解析规则完全不一样。 - JDK版本带来的规则差异:JDK8及更早版本的默认区域数据使用JRE自带的
COMPAT数据源,美式英语(Locale.US)规则下MMM对应3位月份缩写、EEE对应3位星期缩写,和你方数据库存储的字符串格式匹配;从JDK9开始,默认区域数据源切换为CLDR(通用区域数据仓库),部分Locale的日期格式规则发生变更,就会出现部分环境要求全拼才能解析的情况。
修复方案
- 构造
SimpleDateFormat时强制指定和存储字符串匹配的Locale,你方存储的是美式英语的缩写格式,直接显式指定即可,不受用户本地环境配置影响:
- 构造
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy", Locale.US);
- 需兼容多JDK版本的场景,可添加JVM启动参数强制优先使用旧版兼容格式规则:
-Djava.locale.providers=COMPAT,CLDR
- 需兼容多JDK版本的场景,可添加JVM启动参数强制优先使用旧版兼容格式规则:
- (最优方案)如果项目JDK版本≥8,直接弃用线程不安全的
SimpleDateFormat,改用java.time包下的DateTimeFormatter,构造时同样显式指定Locale,既解决线程安全问题,格式规则也更稳定:
- (最优方案)如果项目JDK版本≥8,直接弃用线程不安全的
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz yyyy", Locale.US); ZonedDateTime dateTime = ZonedDateTime.parse("Tue Feb 01 00:00:00 AEDT 2022", formatter);
内容的提问来源于stack exchange,提问作者goshacaracal
相关产品推荐
相关产品推荐

