Многие восхищаются людьми, у которых «вечный календарь в голове» — способность моментально определять день недели, на который приходится произвольная дата, считая даром свыше, недоступным простым людям. Ничуть не принижая достоинств этих людей, хочу отметить, что это не является чем-то сверхъестественным — в основе лежит довольно простая арифметика. Почти каждый может научиться определять день недели, если захочет, без бумажного календаря и калькулятора. За секунду, конечно, это будет получаться далеко не у каждого. Таким качеством могут обладать например люди с синдромом Аспергера, которые способны с огромной скоростью считать в уме.
Что ж, приступим. Скажу сразу, что речь пойдёт о григорианском календаре, применяемом у нас и много где за рубежом.
Начну пожалуй с годов. Потому что это, пожалуй, самое удивительное по соотношению простоты и масштаба. Определить, на какой день приходит одинаковая дата в прошлом или будущем году, зная день в текущем — проще всего. Если сравнить календари двух соседних годов, то можно легко увидеть, что чаще всего они сдвинуты на один день (например, 1 января 2010 года приходится на пятницу, а в 2011 — уже на субботу), и иногда — на два дня, когда вклинивается 29 февраля. Это значит, что очень просто перепрыгнуть на год вперед или назад с любой даты:
Вот например: 13 декабря 2011 года — вторник. Значит в 2011 году это будет понедельник, а в 2012 — четверг (помним про 29 февраля 2012 года).
Слегка расширив предыдущее правило можно так прыгать уже на несколько лет вперёд или назад — смещаемся на столько дней, на сколько лет прыгаем, плюс число перепрыгнутых «високосных дней». При этом чтобы не считать много, выкидываем дни семёрками, ведь сдвинувшись на 7 дней мы вернёмся на тот же день. Возвратимся к предыдущему примеру с 13 декабря: какой у нас день будет, скажем, 13 декабря 2017 года? Разница у нас — 6 лет, плюс в этот промежуток попадает два «високосных дня» — 2012 и 2016 года. То есть надо сдвинуться на 6 + 2 = 8 дней. 7 дней выкидываем, остаётся 1. Вторник плюс 1 день — это ж среда! Смотрим в календарь (у нас есть компьютер, где нетрудно «полистать» года — нажмите на часы в углу экрана!) — так и есть.
При этом хочу особо обратить внимание: надо смотреть именно попадание в интервал даты 29 февраля а не просто сам факт високосного года, ведь между 13 декабря 2011 и 2012 будет два дня недели разницы, а между 12 января тех же годов всего один день, именно из-за того, что 29 февраля не попало в интервал.
С тем как на несколько лет перемещаться — разобрались, но осталось несколько моментов:
Первый — как определить, какой год високосный, а какой — нет? В принципе, все хорошо знают, что високосный год бывает раз в 4 года. Но вдруг понадобится на 13 веков посчитать, как определить високосность произвольного года?
Григорианский календарь, введённый в 1582 году определяет високосными годами следующие:
При этом, обратите внимание, если год делится на 400 он будет делиться и на 100, так что дважды високосным код быть не может. Так что первым делом определяем делимость на 100, а это элементарно: у такого года два нуля в конце: 1600, 1700, 1800.
Если год не «сотый», остаётся определить делимость на 4. Это пожалуй самое сложное в определении високосности. Но не стоит пугаться! Всё на самом деле очень просто. Смотреть на последние две цифры. Если:
то число делится на 4, то есть год високосный. Вот номера всех високосных годов в течение века:
00* | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 |
---|---|---|---|---|---|---|---|---|---|
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
Если не считать 00 года1), то закономерность чётко прослеживается, не так ли?
А что с «сотыми» годами? Да в общем тоже ничего сложного — отбросим две последние цифры и то, что осталось проверим на делимость на 4. Аналогично, делится — високосный, не делится — не високосный.
Хочу сразу заметить, что 2000 год, который многие приняли за вполне рядовой високосный, является на самом деле очень редким исключением, даже исключением из исключения — он выпадает из 4-летнего цикла, так как делится на 100, но зато оказывается в 400-летнем цикле. Да, такое случается только раз в 400 лет!
Ещё одна небольшая хитрость. В течение века, а если границе веков стоит «400-й» год, то и в течение двух веков подряд календари точно повторяются с циклов 28 лет, а значит если мы не перепрыгиваем невисокосный «100-й», и разница между годами составляет 28, 56, 84, (а также, если повезло, 112, 140 и 196 лет) то дни недели у них совершенно точно совпадают. А если не совпадают, то можно отсчитывать дни не через весь интервал, а только от ближайшего совпадающего года. Кстати прибавлять 28 можно прибавляя 30 и отнимая 2, ну и отнимать аналогично, чтобы не мучиться с переносом.
Ещё разок помучаем пример с 13 февраля. Из вышесказанного совершенно очевидно, что как и в 2011, в 1983, 1955, 1927, а также в 2039, 2067 и 2095 год этот день наступает точно во вторник.
С месяцами днями всё оказываются немного сложнее, но только немного.
Для осознания того, что будет сказано ниже следует обратить внимание на одну важную вещь: какой бы мы год не взяли разница в днях недели (да и вообще в днях) между двумя одноимённым датами в этом году будет зависеть только от того, попало ли в интервал 29 февраля, и то отличие будет всего в один день. Так что рассматривать стоит всего два варианта календаря вискосного года и невисокосного.
Вот календарь сферического невисокосного года в вакууме:2)
Январь Февраль Март Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 8 9 10 11 12 13 14 5 6 7 8 9 10 11 5 6 7 8 9 10 11 15 16 17 18 19 20 21 12 13 14 15 16 17 18 12 13 14 15 16 17 18 22 23 24 25 26 27 28 19 20 21 22 23 24 25 19 20 21 22 23 24 25 29 30 31 26 27 28 26 27 28 29 30 31 Апрель Май Июнь Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 1 1 2 3 4 5 6 1 2 3 2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10 9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17 16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24 23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30 30 Июль Август Сентябрь Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 1 1 2 3 4 5 1 2 2 3 4 5 6 7 8 6 7 8 9 10 11 12 3 4 5 6 7 8 9 9 10 11 12 13 14 15 13 14 15 16 17 18 19 10 11 12 13 14 15 16 16 17 18 19 20 21 22 20 21 22 23 24 25 26 17 18 19 20 21 22 23 23 24 25 26 27 28 29 27 28 29 30 31 24 25 26 27 28 29 30 30 31 Октябрь Ноябрь Декабрь Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 1 2 3 4 5 6 7 1 2 3 4 1 2 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3 4 5 6 7 8 9 15 16 17 18 19 20 21 12 13 14 15 16 17 18 10 11 12 13 14 15 16 22 23 24 25 26 27 28 19 20 21 22 23 24 25 17 18 19 20 21 22 23 29 30 31 26 27 28 29 30 24 25 26 27 28 29 30 31
Для того чтобы рассмотреть високосный год, пойдём на хитрость — возьмём год, начинающийся днём раньше, тогда все месяцы, начиная с марта будут совпадать, а сместятся только январь и февраль:
Январь Февраль Март Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс Пн Вт Ср Чт Пт Сб Вс 1 1 2 3 4 5 1 2 3 4 2 3 4 5 6 7 8 6 7 8 9 10 11 12 5 6 7 8 9 10 11 9 10 11 12 13 14 15 13 14 15 16 17 18 19 12 13 14 15 16 17 18 16 17 18 19 20 21 22 20 21 22 23 24 25 26 19 20 21 22 23 24 25 23 24 25 26 27 28 29 27 28 29 26 27 28 29 30 31 30 31
Возьмём два последовательных месяца, и взглянем, в чём разница. Смещение последующего месяца оказывается равно числу дней в предыдущем минус 28, то есть 4 целых недели никак не влияют на смещение, и учитывать можно только остаток из 2 или 3 дней, а у февраля вообще остатка нет, ну либо есть из одного дня, если он високосный.
Так что, например, между 13 ноября и 13 декабря будет разница в 2 дня недели. А что такое вторник минус два дня? Это воскресенье.
На что ещё стоит обратить внимание — месяцы, у которых дни, приходящиеся на одинаковые числа, совпадают:
А также (если посмотреть на календари соседних лет:
Так что, если даты с одинаковым числом пришлись на такие месяцы, то их дни недели будут совпадать!
С днями всё до банальности очевидно. Из разницы в днях просто выкидываем число, кратное неделям (7, 14, 21, 28) и отсчитываем оставшиеся дни недели. Если даты отличаются и годом и месяцем и днём, то просто последовательно суммируем результат.
Описанные выше техники позволяют определить день недели произвольной даты, зная некоторую опорную. Хотя все приведённые шаги достаточно очевидны, тем не менее приведённый способ весьма не быстр. Для того, чтобы вычислять день недели действительно быстро применяется «самый общий алгоритм».
Сначала приведу этот самый общий алгоритм вычисления дня недели (подобный алгоритм применяется и в компьютерных программах, работающих с календарём), потом его разберу.
Причём совсем не нужно всё сначала перемножать, складывать, а затем искать остаток от деления — сложение по модулю считается довольно быстро и просто, как впрочем и умножение. Разница с обычным сложением лишь в том, что после каждой операции вычитайте ближайшее не большее кратное семи — 7, 14, 21, 28, 35 или 42. Тем не менее приведу таблицы сложения и умножения по модулю 7 — можете проверить:
+ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | × | 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
1 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
2 | 2 | 3 | 4 | 5 | 6 | 0 | 1 | 2 | 0 | 2 | 4 | 6 | 1 | 3 | 5 | |
3 | 3 | 4 | 5 | 6 | 0 | 1 | 2 | 3 | 0 | 3 | 6 | 2 | 5 | 1 | 4 | |
4 | 4 | 5 | 6 | 0 | 1 | 2 | 3 | 4 | 0 | 4 | 1 | 5 | 2 | 6 | 3 | |
5 | 5 | 6 | 0 | 1 | 2 | 3 | 4 | 5 | 0 | 5 | 3 | 1 | 6 | 4 | 2 | |
6 | 6 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 6 | 5 | 4 | 3 | 2 | 1 |
Разбор алгоритма будет позже.