Что ж, вы можете просто сказать, посмотрев на него, что это правильно ... Предполагая, что массив t[]
является правильным, что вы можете проверить с помощью всего 12 выборочных проверок (по одной на каждый месяц, используя любой день / год) .
y -= m < 3
хороший трюк. Он создает «виртуальный год», который начинается 1 марта и заканчивается 28 февраля (или 29), добавляя дополнительный день (если таковой имеется) в конец года; или, скорее, в конце предыдущего года. Например, виртуальный 2011 год начался 1 марта и закончится 29 февраля, а виртуальный 2012 год начнется 1 марта и закончится 28 февраля.
Если добавить дополнительный день для високосных лет в конце виртуального года, остальное выражение существенно упростится.
Давайте посмотрим на сумму:
(y + y/4 - y/100 + y/400 + t[m-1] + d) % 7
В нормальном году 365 дней. Это 52 недели плюс 1 день. Таким образом, день недели смещается на один день в год в целом. Именно этому способствует термин y
; это добавляет один к дню для каждого года.
Но каждые четыре года - високосный. Те вносят дополнительный день каждые четыре года. Благодаря использованию виртуальных лет мы можем просто добавить y/4
к сумме, чтобы подсчитать, сколько високосных дней происходит за y
лет. (Обратите внимание, что эта формула предполагает целочисленные деления вниз .)
Но это не совсем правильно, потому что каждые 100 лет не високосный год. Таким образом, мы должны вычесть y/100
.
За исключением того, что каждые 400 лет снова високосный год. Поэтому мы должны добавить y/400
.
Наконец, мы просто добавляем день месяца d
и смещение от таблицы, которое зависит от месяца (поскольку границы месяца в году довольно условны).
Тогда возьмите весь мод 7, так как это то, сколько длится неделя.
(Например, если бы недели были восемь дней, что бы изменилось в этой формуле? Что ж, это был бы мод 8, очевидно. Также y
должно было бы быть 5*y
, потому что 365% 8 == 5 Также необходимо скорректировать таблицу месяцев t[]
. Вот и все.)
Кстати, утверждение Википедии о том, что календарь «хорош до 9999 года», совершенно произвольно. Эта формула хороша, как бы долго мы ни придерживались григорианского календаря , будь то 10, 100, 1000 или 1 миллион лет.
[править]
Приведенный выше аргумент по сути является доказательством по индукции. То есть предполагая , что формула работает для определенного (y, m, d), вы доказываете , что она работает для (y + 1, m, d) и (y, м, d + 1). (Где у - «виртуальный год», начинающийся 1 марта.) Итак, ключевой вопрос: меняется ли сумма на правильную сумму при переходе от одного года к следующему? Со знанием правил високосного года и с «виртуальным годом», имеющим дополнительный день в конце года, это тривиально.