Java 1.6中DatatypeConverter与SimpleDateFormat解析0001日期结果不一致
为什么Java 1.6中解析0001年日期会出现不一致?
你遇到的这个问题核心是Java 1.6里两种日期解析工具对公元早期日期的历法处理逻辑不一样,再结合时区规则的影响,导致了结果差异。我来帮你拆解一下:
1. 两种工具的历法规范差异
SimpleDateFormat依赖的GregorianCalendar默认用的是混合历法:1582年10月15日之后使用格里高利历,之前自动切换为儒略历(这对应历史上真实的历法变更场景)。DatatypeConverter.parseDateTime()是遵循XML Schema的dateTime规范实现的,它要求所有日期都使用格里高利历——哪怕是公元元年这么早的日期,也不会切换到儒略历。
当解析"0001-01-01"时:
SimpleDateFormat用儒略历计算这个日期的时间戳,对应儒略历的1月1日。DatatypeConverter用格里高利历计算,而儒略历的0001-01-01正好对应格里高利历的0001-01-03——这就是你看到两个日期差2天、时间戳差172800000毫秒(正好2天)的原因。
2. 为什么1980年的日期结果一致?
1980年远在1582年的历法变更之后,不管是混合历法还是纯格里高利历,计算出来的日期都是完全相同的,所以两种解析工具的结果就自然对齐了。
验证结论的小技巧
你可以试试解析1582年10月4日和10月15日:SimpleDateFormat会跳过10月5日到14日(这是儒略历转格里高利历的历史变更),而DatatypeConverter则能正常解析这些中间日期——因为它全程用格里高利历。
解决方案:统一解析逻辑
如果需要让两种方式的结果一致,你可以选以下一种方式:
- 统一用
DatatypeConverter解析XML格式的日期,严格遵循XML Schema规范。 - 给
SimpleDateFormat强制设置纯格里高利历的Calendar:
这样修改后,SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("Asia/Novosibirsk")); // 强制GregorianCalendar对所有日期使用格里高利历,不切换到儒略历 gc.setGregorianChange(new Date(Long.MIN_VALUE)); simpleDateFormat.setCalendar(gc);SimpleDateFormat解析"0001-01-01"的结果就会和DatatypeConverter完全一致了。
内容的提问来源于stack exchange,提问作者Wizzard
相关产品推荐
相关产品推荐

