Java 8中LocalDateTime设为年份0时DateTimeFormatter格式化异常问题
问题原因与修复方案
为什么格式化结果不一致?
根源在于DateTimeFormatter的模式符号和自定义格式化器对应的年份字段完全不同:
yyyy/yy对应的是时代年份(ChronoField.YEAR_OF_ERA):现行公历体系里没有公元0年,公元1年的前一年是公元前1年(1 BCE)。Java的LocalDateTime用**连续年份(Proleptic Year)**统一表示时间,其中withYear(0)对应历法中的公元前1年。当用yyyy/yy格式化时,默认采用公元(CE)时代,公元前1年在该时代下会被映射为时代年份1,因此输出0001和01。- 你自定义的
yyy直接绑定了连续年份(ChronoField.YEAR):这个字段直接使用Java内部的连续年份数值(支持0、负数),所以年份0能被正确格式化为000。
怎么修复?
要正确处理包含0或负数的年份,有两种可行方案:
- 使用连续年份专用模式符号:把
yyyy换成uuuu,yy换成uu,这两个符号是专门为连续年份设计的:
DateTimeFormatter uu = DateTimeFormatter.ofPattern("uu"); DateTimeFormatter uuuu = DateTimeFormatter.ofPattern("uuuu"); // 格式化year0 System.out.println("year0.format(uuuu): " + year0.format(uuuu)); // 输出 0000 System.out.println("year0.format(uu): \t" + year0.format(uu)); // 输出 00
- 用
DateTimeFormatterBuilder自定义格式:和你构建yyy的逻辑一致,指定ChronoField.YEAR来生成两位年份的格式化器:
DateTimeFormatter fixedYy = new DateTimeFormatterBuilder() .appendValueReduced(ChronoField.YEAR, 2, 2, 0) .toFormatter(); System.out.println("year0.format(fixedYy): " + year0.format(fixedYy)); // 输出 00
修复后验证
调整后,year0的格式化结果会符合预期:
uuuu模式输出0000uu或自定义格式化器输出00
内容的提问来源于stack exchange,提问作者Guo
相关产品推荐
相关产品推荐

