Java говорит, что год 0 - високосный год, но год 0 никогда не существовал

Я писал несколько тестовых примеров для некоторых методов удобства, которые я обновляю, и решил посмотреть, что произойдет, если бы я использовал LocalDate isLeapYear() на год 0. Насколько я понимаю, год 0 никогда не существовал: за год до 1 года был 1 до н.э. (Это основано на статье, которую я прочитал много лет назад, чей источник, о котором я давно забыл.) К большому удивлению, мой тест показал, что год 0 високосный год!

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

Другая возможность заключается в том, что статья, которую я прочитал, была просто ошибочной. (Или это было правильно, но позже переосмыслено).

Это не очень важно, но мне любопытно узнать, где ошибка: ISO-8601, класс Java LocalDate или мое понимание того, как отсчитывается время.

Ответ 1

TL; DR: LocalDate выполняет то, что документировано, по международному стандарту (ISO 8601). Является ли это "правильным" или нет, это совершенно другой вопрос.

Сам LocalDate Javadoc включает это предостережение:

Это эквивалентно прорептической григорианской системе календаря, в которой сегодня правила для високосных лет применяются на все времена. Для большинства приложений, написанных сегодня, правила ISO-8601 вполне подходят. Тем не менее, любое приложение, использующее исторические даты, и требует, чтобы они были точными, не находят подход ISO-8601 непригодным.

В Википедии есть дополнительная информация о прорептическом григорианском календаре. Среди прочего, в нем говорится:

Математически удобнее включать год 0 и представлять более ранние годы как отрицательные, с конкретной целью облегчения расчета количества лет между отрицательным (BC) годом и положительным (AD) годом. Это конвенция, используемая в астрономической нумерации года и в международной стандартной системе дат ISO 8601. В этих системах год 0 является високосным годом.

Простите меня, пока я отвлекаюсь на какой-то исторический контекст для всего этого.

Годы в западном календаре якобы подсчитываются с момента рождения Иисуса Христа, но идея этого началась в шестом веке, и наш текущий календарь основан на расчетах, сделанных в шестнадцатом веке. Поскольку римские цифры не имели представления о нуле или отрицательных числах, годы считались "после Иисуса" (AD, для anno domini) или "до Иисуса" (до н.э., "до Христа"). Таким образом, традиционно 1 БК последовали AD 1, без нулевого года между ними.

Однако в первом столетии никто не считал годы таким образом; для сравнения, Евангелие от Луки описывает год, когда Иисус начал свое служение как

в пятнадцатый год царствования Тиберия Цезаря, Понтий Пилат, являющийся правителем Иудеи, и Ирод являлся тетрархом Галилейского и братом его Филиппом четвертичным принцем Итуры и района Трахонитиса, а Лисания - четвертым царем Абилина,

Очевидно, это было бы 30 лет, так как Люк описывает Иисуса как "лет тридцати" в то время. Но современные историки в целом согласны с тем, что Дионисий Экзигус, который предложил систему анно домини в 525 г. н.э., ошибался, и, следовательно, нумерация лет уходит не менее одного или двух лет. (Точная дата по-прежнему несколько противоречива, см. Википедию, если вы заботитесь о более подробной информации.)

Но это слишком поздно для исправления; даже переход от юлианского к григорианскому календарю, который был несоответствием менее двух недель, был встречен с широким политическим сопротивлением, поскольку переход произошел во всей Европе в течение нескольких столетий - вы можете себе представить, как разрушительная смена годовой нумерации теперь будет!

Так что же эта история связана с программным обеспечением сегодня? К сожалению, из-за множества способов, в которых даты были рассчитаны и записаны на протяжении всей истории, вам нужно либо отказаться от календаря, вести себя последовательно, когда вы двигаетесь вперед и назад во времени, или вам нужно отказаться от расчетных дат имея любую переписку с датами, которые настоящие люди использовали бы в то время. Дивергенция происходит быстрее, чем вы думаете: многие европейские страны по-прежнему используют юлианский календарь менее 100 лет назад, с расхождением почти двух недель от всех остальных в Европе!


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

Ответ 2

Из Википедии:

... в астрономическом году насчитывается нулевой год (где он совпадает с юлианским годом 1 г. до н.э.) и в ИСО 8601: 2004 (где он совпадает с григорианским годом 1 г. до н.э.)