Java说0年是a年,但0年不存在


74

我正在为一些要更新的便捷方法编写一些测试用例,并决定看看如果在0年使用LocalDateisLeapYear()方法会发生什么。据我所知,0年实际上不存在:公元1年之前是1年公元前。(这是基于我多年以前读过的一篇文章,该文章我早就忘记了。)令我惊讶的是,我的测试表明0年是a年!

我意识到java.time.LocalDate该类实现了ISO-8601,但是ISO-8601确实表明存在0年吗?我不愿意相信被测试的人LocalDate会错过这个作为测试用例,但是我也不愿意相信像ISO-8601这样的国际标准会犯这样一个明显的错误。

另一种可能性是我阅读的文章完全是错误的。(或者那是正确的,但后来又重新考虑了。)

这不是很重要,但是我很想知道错误在哪里:ISO-8601,Java的LocalDate类,或者我对时间的估算方法。


1
谢谢大家!我很高兴看到LocalDate没有明显的错误。我将不得不习惯于像一个带有负值,零值和正值的温度计的时间线来思考……。–
亨利

3
实际上,真正的问题是日历系统在历史上一直不一致。您可以使用现代日历讨论任意过去的日期,但是如果您想读取任意过去的日期,或者将计算出的日期与任意历史事件对齐,则问题很快就会变得不仅困难,而且对于许多日期实际上是不可能的。为了我们自己的方便,“零年”的想法是现代发明。在零年级(或一个BCE或您写的那个)生活的人不会知道发生了什么重大事件。
丹尼尔·普瑞登

Daniel Pryden-是的,我知道计时方面的许多挑战。我只是不知道为了简化计算而发明了0年。;-)
亨利

Answers:


107

TL; DR:LocalDate正在按照国际标准(ISO 8601)进行记录的工作。这是否“正确”是一个完全不同的问题。

LocalDateJavadoc中本身就包含这个警告:

它等效于多用的格里高利历系统,该系统在今天一直适用today年的规则。对于当今编写的大多数应用程序,ISO-8601规则完全适用。但是,任何利用历史日期并要求它们准确的应用程序都将发现ISO-8601方法不合适。

维基百科上有更多有关公历的信息。其中包括:

从数学上讲,将年份0包括在内并将较早的年份表示为负数更为方便,其特定目的是为了便于计算负(BC)年和正(AD)年之间的年数。这是天文年份编号和国际标准日期系统ISO 8601中使用的约定。在这些系统中,0年是a年。

请原谅我一会儿,以便我能谈谈所有这些历史背景。

表面上的历法从表面上看是从耶稣基督的出生开始算起的,但是这样做的想法始于六世纪,而我们目前的历法是基于十六世纪的计算得出的。由于罗马数字既不代表零,也不代表负数,所以年份要么在“耶稣之后”(AD,对于anno domini)要么在“耶稣之前”(BC,对于“在基督之前”)计算。因此,按照传统,公元前1个后跟公元1个,之间没有零年。

但是,在第一世纪,没有人以这种方式计算年份。为了比较,路加福音将耶稣开始传道的那年描述为

在提比略·凯撒(Tiberius Caesar)统治的十五年里,庞蒂乌斯·彼拉多(Pontus Pilate)担任犹大州长,希律(Herod)担任加利利的四分之一,他的兄弟菲利普·四分之一的伊图拉亚和风管炎地区,而利萨尼亚(Lysanias)的四分之一是阿比林,

表面上看,这本来应该是公元30年,因为卢克当时将耶稣描述为“大约三十岁”。但是现代历史学家普遍认为,狄奥尼修斯·埃希古斯(Dionysius Exiguus)在公元525年提出了安诺多米尼系统,但它弄错了,因此年数至少减少了一两年。(确切的日期还是有争议的;如果您想了解更多详细信息,请参阅Wikipedia。)

但是现在修复为时已晚。甚至从朱利安历法到格里高利历的转换(相差不到两周)也遇到了广泛的政治阻力,因为整个欧洲的转换历时数个世纪-您可以想像年号变更的破坏性会是现在!

那么,这段历史与今天的软件有什么关系?不幸的是,由于在整个历史中计算和记录日期的方式多种多样,因此您要么在时间向前和向后移动时以一致的方式放弃日历,要么必须放弃计算的日期与真实人当时使用的日期有任何对应关系。差异发生的速度比您想象的要快:不到100年前,许多欧洲国家仍在使用儒略历,与欧洲其他国家相差将近两个星期!


可以理解的是,LocalDate洗手间会弄得一团糟,只能按照我们今天使用它的方式来实现日历。重申Javadoc的说法:“对于当今编写的大多数应用程序,ISO-8601规则是完全合适的。但是,任何使用历史日期并要求它们准确的应用程序都会发现ISO-8601方法不合适。”


11
很高兴知道他们知道自己的局限性。好发现。
阿兰·克鲁兹

6
汤姆·斯科特(Tom Scott)有关此主题的必修视频:youtube.com/watch?v=-5wpm
丹,

3
计时的历史令人着迷。我读到的一则轶事说,当拿破仑是欧洲的祸害时,俄国人和德国人(或英语?)有代表开会,他们同意在一定日期在某个地方集结各种军队。(我不记得日期或地点。)除俄国人外,每支军队都在指定的日期出现:该日期仍是未来两周左右,他们仍在前进....盟友忘记了俄罗斯人仍在使用儒略历,而其他人则使用公历。
亨利

1
@亨利是如此。人们一见钟情的如此“显而易见”的事情变成了将代码编码到库中的噩梦。还要保持!(嘿,让我们在我们的国家停止使用夏令时!嘿,让我们在今年的最后一天添加一秒钟!)
Pac0

1
类似的警告适用于GregorianCalendar:“GregorianCalendar工具proleptic。格里高利历和罗马儒略历也就是说,日期是由外推当前规则无限远的向后和向前的时间来计算。但是,使用获得的日期。GregorianCalendar在历史上是准确的只有从3月1日,公元4起,当采用现代儒略历规则时。在此日期之前,leap年规则被不定期地应用…”
200_success

10

维基百科

...天文年份编号(与公元前1年的儒略年相重合)和ISO 8601:2004(公历BC年的公历年相重合)有零年


注意:元旦以前是3月25日,但还有更多的日子,因此年份排成一行,因此在格里高利历(Gregorian calender)的情况下,日期将更接近3月12日。
彼得·劳瑞
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.