Java каже, що рік 0 є високосним, але рік 0 ніколи не існував


74

Я писав кілька тестових кейсів для деяких зручних методів, які я оновлюю, і вирішив подивитися, що станеться, якщо я LocalDateзастосую isLeapYear()метод 0-го року. Як я розумію, рік 0 насправді ніколи не існував: рік до 1 р. Н. Е. Був 1 Е. (Це засновано на статті, яку я прочитав багато років тому, джерело якої я давно забув.) На мій подив, мій тест показав, що 0 рік є високосним!

Я усвідомлюю, що java.time.LocalDateклас імплементує ISO-8601, але чи справді ISO-8601 вказує на те, що рік 0 існував? Я неохоче вірю, що люди, які тестували LocalDate, пропустили б це як тест, але я також не хочу вірити, що такий міжнародний стандарт, як ISO-8601, зробить таку очевидну помилку.

Інша можливість полягає в тому, що стаття, яку я прочитав, була просто абсолютно неправильною. (Або тоді це було правильно, але згодом було переосмислено).

Це не надзвичайно важливо, але мені цікаво дізнатись, де помилка: ISO-8601, LocalDateклас Java або моє розуміння того, як рахується час.


1
Дякую всім! Я радий бачити, що LocalDate не має очевидної помилки. Мені доведеться звикнути думати про часову шкалу, як термометр, із негативними, нульовими та позитивними значеннями знову ....
Генрі

3
Насправді, справжнє питання полягає в тому, що календарні системи в минулому були суперечливі. Ви можете використовувати сучасний календар, щоб говорити про дати у довільному минулому, але якщо ви хочете прочитати дати у довільному минулому або узгодити розраховані дати з довільними історичними подіями, проблема швидко стає не просто складною, але для багатьох дат фактично неможливою. Ідея "нульового року" - це сучасний винахід, для власної зручності. Люди, які жили в нульовий час року (або один рік до н. Е., Або як ви це пишете), не знали б, що сталося щось значне.
Даніель Прайден,

Даніель Прайден - Так, я знаю деякі з багатьох викликів, пов’язаних із хронометражем. Я просто не знав, що рік 0 був винайдений для полегшення розрахунків. ;-)
Генрі

Відповіді:


107

TL; DR: LocalDateробить те, що зафіксовано, виконуючи міжнародний стандарт (ISO 8601). "Правильно" це чи ні - це вже зовсім інше питання.

Сам LocalDateJavadoc включає це застереження:

Це еквівалентно пролептичній григоріанській системі календаря, в якій сучасні правила високосного року застосовуються на всі часи. Для більшості програм, написаних сьогодні, правила ISO-8601 цілком підходять. Однак будь-яка програма, яка використовує історичні дати та вимагає їх точності, визнає підхід ISO-8601 непридатним.

У Вікіпедії є більше інформації про пролептичний григоріанський календар . Серед іншого, там сказано:

Математично зручніше включати рік 0 і представляти попередні роки як від’ємні, з конкретною метою полегшення обчислення кількості років між від’ємним (BC) та позитивним (AD) роком. Це домовленість, яка використовується в астрономічній нумерації року та в міжнародній стандартній системі дат, ISO 8601. У цих системах 0 рік є високосним.

Пробачте мене, поки я заглиблююся в якийсь історичний контекст усього цього.

Роки в західному календарі нібито відлічуються від народження Ісуса Христа, але ідея цього почалася в шостому столітті, а наш сучасний календар базується на розрахунках, зроблених у шістнадцятому столітті. Оскільки римські цифри не представляли ні нуля, ні негативних чисел, роки зараховували або "після Ісуса" (н.е., для anno domini ), або "до Ісуса" (до н. Е., "До Христа"). Таким чином, традиційно за 1 р. До н. Е. Слідував 1 р. Н.е.

Однак у першому столітті ніхто так не рахував роки; для порівняння, Євангеліє від Луки описує рік, коли Ісус розпочав своє служіння, як

на п'ятнадцятому році правління Тиберія Цезаря, Понтій Пілат - намісник Іудеї, а Ірод - тетрарх Галілеї, а його брат Філіп - тетрарх Ітуреї та району Трахоніт, а Лісаній - тетрарх Ебіліні,

Нібито це було б 30 р. Н. Е., Оскільки Лука описує Ісуса на той час «близько тридцяти років». Але сучасні історики загалом сходяться на думці, що Діонісій Екзигус, який запропонував систему anno domini в 525 р. Н. Е., Помилився, і, отже, нумерація років зменшується принаймні на один-два роки. (Точна дата все ще дещо суперечлива; див. Вікіпедію, якщо вам потрібні докладніші відомості.)

Але пізно це виправляти зараз; навіть перехід від юліанського до григоріанського календаря, що суперечило менше двох тижнів, зустрів великий політичний спротив, оскільки перехід відбувся по всій Європі протягом декількох століть - ви можете собі уявити, наскільки руйнівною є зміна року було б зараз!

То яке відношення має ця історія до програмного забезпечення сьогодні? На жаль, через незліченну кількість способів обчислення та запису дат протягом історії, вам або потрібно відмовитись від календаря, що поводиться послідовно, коли ви рухаєтеся вперед і назад у часі, або вам потрібно відмовитись від обчислених дат маючи будь-яку відповідність датам, якими тоді користувались би реальні люди. Розбіжності відбуваються швидше, ніж ви можете подумати: багато європейських країн все ще користувались юліанським календарем менше 100 років тому, з відхиленням майже у два тижні від усіх інших в Європі!


Зрозуміло, що LocalDateмиє руки від цього безладу і впроваджує календар лише так, як ми використовуємо його сьогодні. Повторюючи те, що сказано в Javadoc: "Для більшості програм, написаних сьогодні, правила ISO-8601 цілком підходять. Однак будь-яка програма, яка використовує історичні дати і вимагає від них точності, визнає підхід ISO-8601 непридатним".


11
Добре знати, що вони знають про свої обмеження. Приємна знахідка.
Ален Круз,

6
Обов’язкове відео Тома Скотта на цю тему: youtube.com/watch?v=-5wpm-gesOY
Dan

3
Історія відліку часу захоплює. Один анекдот, який я прочитав, говорить, що коли Наполеон був бичем Європи, росіяни та німці (чи англійці?) Мали зустрітися представники, і вони домовились про те, щоб їхні різні армії збиралися в певному місці в певну дату. (Я не пам’ятаю ні дати, ні місця.) Кожна армія з’явилася в призначену дату, крім росіян: ця дата була ще майже два тижні в майбутньому, і вони все ще йшли в похід .... Союзники забули, що Росіяни все ще користувалися юліанським календарем, тоді як інші - григоріанським.
Генрі

1
@ Генрі так правда. І щось настільки «очевидне» на перший погляд для людей стає кошмаром для кодування в бібліотеці. А також підтримувати! (Гей, припинимо використовувати перехід на літній час у нашій країні! Гей, додамо секунду в останній день цього року!)
Pac0

1
Подібні застереження стосуються GregorianCalendar: " GregorianCalendarреалізує пролептичний григоріанський та юліанський календарі. Тобто дати обчислюються шляхом екстраполяції діючих правил на невизначений час далеко назад і вперед у часі. ... Однак дати, отримані з використанням, GregorianCalendarє історично точними лише з 1 березня 4 року нашої ери, коли були прийняті сучасні правила юліанського календаря. До цієї дати правила високосного року застосовувались нерегулярно ... "
200_success

10

З Вікіпедії :

... існує нульовий рік в астрономічній нумерації року (де це збігається з юліанським роком 1 до н. е.) та в ISO 8601: 2004 (де він збігається з григоріанським роком 1 до н. е.)


Примітка: раніше день нового року був 25 березня, але мав трохи більше днів, тому роки все ж вишикувалися, так що це було б ближче до 12 березня під григоріанським календарем.
Пітер Лорі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.