我正在为一些正在更新的便捷方法编写一些测试用例,并决定看看如果在第0年使用LocalDate
的{{1}}方法会发生什么。据我所知, 0年实际上从未存在过:1 AD之前的年份是1 BC。 (这是基于我多年以前读过的一篇文章,该文章我早已忘记了。)令我惊讶的是,我的测试表明0年是a年!
我意识到isLeapYear()
类实现了ISO-8601,但是ISO-8601是否真的表明存在0年?我不愿意相信测试java.time.LocalDate
的人会错过此作为测试用例,但是我也不愿意相信像ISO-8601这样的国际标准会犯这样一个明显的错误。
另一种可能性是,我阅读的文章完全是错误的。 (或者那是正确的,但后来又重新考虑了。)
这并不是很重要,但是我很想知道错误在哪里:ISO-8601,Java的LocalDate
类,或者我对时间的理解。
答案 0 :(得分:105)
TL; DR:LocalDate
正在按照国际标准(ISO 8601)进行记录中的工作。这是否“正确”是一个完全不同的问题。
LocalDate
Javadoc本身包括以下警告:
它等效于多用的格里高利历系统,该系统在今天始终适用time年的规则。对于当今编写的大多数应用程序,ISO-8601规则完全适用。但是,任何使用历史日期并要求准确的应用程序都会发现ISO-8601方法不合适。
维基百科上有关proleptic Gregorian calendar的更多信息。其中包括:
从数学上讲,更方便的是包含年份0并将较早的年份表示为负数,具体目的是为了便于计算负(BC)年和正(AD)年之间的年数。这是天文年份编号和国际标准日期系统ISO 8601中使用的约定。在这些系统中,0年是a年。
请原谅我一会儿,以便讨论所有这些历史背景。
表面上的历年从耶稣基督的出生开始算起,但是这样做的想法始于六世纪,而我们目前的历法是基于十六世纪的计算得出的。由于罗马数字既不代表零,也不代表负数,因此年份要么在“耶稣之后”(公元,对于“安诺多米尼”)中计算,要么在“耶稣之前”(BC,对于“在基督之前”)中计算。因此,按照惯例,在公元前1年之后是公元1年,之间没有零年。
但是,在第一个世纪,没有人以这种方式计算年份。作为比较,路加福音将耶稣开始传道的那年描述为
在提比略·凯撒(Tiberius Caesar)统治的第15年,庞蒂乌斯·彼拉多(Pontus Pilate)担任犹大的州长,希律(Herod)担任加利利的四分之一,他的兄弟菲利普·四分(Ituraea)和沙眼炎地区的四分之一,利萨尼亚(Lysanias)的四分之一是阿比林(Abilene)的四分之一, / p>
由于卢克(Luke)当时将耶稣描述为“大约三十岁”,因此表面上看这应该是公元30年。但是现代历史学家普遍认为,在公元525年提出anno domini系统的狄奥尼修斯·埃希古斯(Dionysius Exiguus)弄错了,因此年份的编号至少间隔了一两年。 (确切的日期还是有争议的;如果您想了解更多详细信息,请参见Wikipedia。)
但是现在修复为时已晚。甚至从朱利安历法到格里高利历的转换(相差不到两周)都遇到了广泛的政治阻力,因为整个欧洲的转换历时数个世纪之久-您可以想像年号变更的破坏性会是现在!
那么这段历史与今天的软件有什么关系?不幸的是,由于在整个历史中计算和记录日期的方式多种多样,因此您要么在前进后退时都以一致的方式放弃日历,要么必须放弃计算出的日期与真实人当时使用的日期有任何对应关系。这种差异发生的速度比您想象的要快:不到100年前,许多欧洲国家仍在使用儒略历,与欧洲其他国家相差将近两个星期!
可以理解的是,LocalDate
洗手时会弄得一团糟,仅以我们今天使用它的方式来实现日历。重申Javadoc的说法:“对于当今编写的大多数应用程序,ISO-8601规则是完全合适的。但是,任何使用历史日期并要求它们准确的应用程序都会发现ISO-8601方法不合适。 。”
答案 1 :(得分:10)
来自Wikipedia:
...天文学年编号(与儒略历1 BC一致)和ISO 8601:2004(与公历BC公历1一致)存在零年