Java says the year 0 is a leap year but year 0 never existed

Henry :

I was writing some test cases for some convenience methods that I am updating and decided to see what would happen if I used LocalDate's isLeapYear() method on the year 0. As I understand it, year 0 never actually existed: the year before 1 AD was 1 BC. (This is based on an article I read many years ago whose source I have long forgotten.) Much to my surprise, my test indicated that the year 0 wa a leap year!

I realize that the java.time.LocalDate class implements ISO-8601 but does ISO-8601 really indicate that the year 0 existed? I'm reluctant to believe that the people who tested LocalDate would have missed this as a test case but I'm also reluctant to believe that an international standard like ISO-8601 would make such an obvious mistake.

The other possibility is that the article I read was just flat-out wrong. (Or it was correct then but was rethought later.)

This is not hugely important but I am curious to know where the mistake is: ISO-8601, Java's LocalDate class, or my understanding of how time is reckoned.

Daniel Pryden :

TL;DR: LocalDate is doing what it is documented to do, following an international standard (ISO 8601). Whether this is "correct" or not is a whole different question.

The LocalDate Javadoc itself includes this caveat:

It is equivalent to the proleptic Gregorian calendar system, in which today's rules for leap years are applied for all time. For most applications written today, the ISO-8601 rules are entirely suitable. However, any application that makes use of historical dates, and requires them to be accurate will find the ISO-8601 approach unsuitable.

Wikipedia has more information on the proleptic Gregorian calendar. Among other things, it says:

Mathematically, it is more convenient to include a year 0 and represent earlier years as negative, for the specific purpose of facilitating the calculation of the number of years between a negative (BC) year and a positive (AD) year. This is the convention used in astronomical year numbering and in the international standard date system, ISO 8601. In these systems, the year 0 is a leap year.

Forgive me a moment while I digress into some historical context for all this.

Years in the Western calendar are ostensibly counted from the birth of Jesus Christ, but the idea of doing so started in the sixth century and our current calendar is based on calculations made in the sixteenth century. Since Roman numerals had no representation of zero nor of negative numbers, years were either counted "after Jesus" (AD, for anno domini) or "before Jesus" (BC, for "before Christ"). Thus, traditionally, 1 BC was followed by AD 1, with no year zero between.

However, in the first century, nobody counted years that way; for comparison, the Gospel of Luke describes the year when Jesus began his ministry as

in the fifteenth year of the reign of Tiberius Caesar, Pontius Pilate being governor of Judaea, and Herod being tetrarch of Galilee, and his brother Philip tetrarch of Ituraea and of the region of Trachonitis, and Lysanias the tetrarch of Abilene,

Ostensibly this would have been AD 30, since Luke describes Jesus as being "about thirty years of age" at the time. But modern historians generally agree that Dionysius Exiguus, who proposed the anno domini system in AD 525, got it wrong, and thus the numbering of years is off by at least one or two years. (The exact date is still somewhat controversial; see Wikipedia if you care for more detail.)

But it's too late to fix now; even the transition from the Julian to Gregorian calendar, which was a discrepancy of less than two weeks, was met with extensive political resistance as the changeover occurred throughout Europe over a period of several centuries -- you can imagine how disruptive a change of year numbering would be now!

So what does this history have to do with software today? Unfortunately, due to the myriad ways in which dates were calculated and written down throughout history, you either need to give up on the calendar behaving in a consistent way as you move forward and backward in time, or you have to give up on calculated dates having any correspondence to the dates that real people would have used at the time. The divergence happens more rapidly than you might think: many European countries were still using the Julian calendar less than 100 years ago, with a discrepancy of nearly two weeks from everyone else in Europe!


Understandably, LocalDate washes its hands of this mess and only implements the calendar the way we use it today. Reiterating what the Javadoc says: "For most applications written today, the ISO-8601 rules are entirely suitable. However, any application that makes use of historical dates, and requires them to be accurate will find the ISO-8601 approach unsuitable."

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=34880&siteId=1