慎用 Java 日期格式化

  • 曹知渊

2015 年 1 月 4 日

话题:Java语言 & 开发架构

2014 年 12 月 29 日,Reddit上一条寥寥几语的留言引起了大量的回复,这条留言说道:

今天有可能变成 2015 年 12 月,快点修复它。

这条留言实际指向了 Twitter 上的一个帖子,这个帖子提醒大家,如果使用了 YYYY 的格式符来格式化日期,那么就有可能用错格式了。

Reddit 的一位读者解释说,Twitter 由于误用格式符,把当天的日期变成了 2015 年 12 月的某天。

那么日期为什么忽然变得不对了?原因是开发人员误用的格式符代表的是一种不同的日历系统。现行的公历通常被称为格里高利历(Gregorian calendar),它以 400 年为一个周期,在这个周期中,一共有 97 个闰日,在这种历法的设计中,闰日尽可能均匀地分布在各个年份中,所以一年的长度有两种可能:365 天或 366 天。而本文提到的被错误使用的历法格式,是国际标准 ISO 8601 所指定的历法。这种历法采用周来纪日,样子看起来是这样的:2009-W53-7。对于格里高利历中的闰日,它也采用“闰周”来表示,所以一年的长度是 364 或 371 天。并且它规定,公历一年中第一个周四所在的那个星期,作为一年的第一个星期。这导致了一些很有意思的结果,公历每年元旦前后的几天,年份会和 ISO 8601 纪年法差一年。比如,2015 年的第一个周四是 1 月 1 日,所以 1 月 1 日所在的那周,就变成了 2015 年的第一周。代表 ISO 8601 的格式符是YYYY,注意是大写的,而格里高利历的格式符是小写的yyyy,如果不小心把这两者搞混了,时间就瞬间推移了一年!维基百科上也有词条专门解释 ISO 8601。

作为 Java 开发者,只要搞清楚YYYYyyyy区别,准确地使用两者,就不会出现这种错误。Reddit 的评论中也有读者提到,在Joda Time中,使用YYYY是没有问题的。


感谢郭蕾对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

Java语言 & 开发架构