Как стать автором
Обновить

Календарь древних майя — как вычислить дату?

Время на прочтение 6 мин
Количество просмотров 19K
Здравствуй, читатель!

Если ты помнишь, то совсем недавно календарь древних майя был у всех на слуху. Мало кто обошёл вниманием тему животрепещущего вопроса окончания летосчисления некогда великой цивилизации. Сейчас я предлагаю вникнуть в математическую суть вопроса — как вычислить дату календаря майя.

В своём повествовании я покажу как получить дату календаря майя из даты привычного нам григорианского календаря, приводя примеры алгоритмов на языке Python.

Для начала вкратце повторим теорию самого календаря.

Состоит календарь майя из трёх основных частей. Это — длинный счёт, цолькин и хааб.

Четвёртой не обязательной частью календаря является перечисление владык ночи. Их всего девять и они следуют друг за другом. Что-то похожее на девятидневную неделю. Имена владык не сохранились, так что принято их обозначать просто: G1, G2, G3, G4, G5, G6, G7, G8, G9.

Что ещё следует знать? Доподлинно не известно, с какого дня григорианского календаря следует вести отсчёт. По этому поводу существует множество авторитетных мнений, но популярны сейчас две версии — так называемые корреляции 584283 и 584285. Первую называют GMT-корреляцией, вторую — корреляцией Thompson-Lounsbury или астрономической корреляцией. Отмечу, что 21 декабря 2012 года — конец летосчисления по GMT‑корреляции, но в последнее время всё больше поддерживается мнение, что вторая корреляция более верна. По ней «конец всего сущего» наступает на два дня позже — 23 декабря 2012 года. Ура, товарищи! Нам конечно же от этого намного легче.

Итак… Все календарные величины можно вычислить, зная количество дней с начала майянской эры. Будем их условно называть «майянские дни», по аналогии с юлианскими днями.

Майянские дни для дат нашей эры вычисляются как остаток от деления выражения (D + 1721425 – C) на 1872000, где D — количество дней с начала нашей эры до заданной даты, C — значение корреляции, 1872000 — количество дней в майянской эре. Таким образом на Python формула имеет вид:
M = (D + 1721425 – C) % 1872000

значение D в Python получить весьма легко, достаточно импортировать модуль datetime и тогда, если текущая дата равна current_date = datetime.date.today(), то D = current_date.toordinal(). Либо же просто — D = datetime.date.today().toordinal()

Теперь, зная значение майянских дней, мы можем вычислить всё остальное. Начнём с длинного счёта.

Длинный счёт — это счёт кинов (1 кин = 1 день), 20 кинов составляют 1 винал, 18 виналов составляют 1 тун или 20×18=360 кинов, 20 тунов — 1 катун или 20×18×20=7200 кинов, 20 катунов — 1 бактун или 20×18×20×20=144000 кинов. Эра состоит из 13 бактунов, следовательно эра длится 20×18×20×20×13=1872000 кинов. Для примера, последняя дата майянской эры по длинному счёту будет 12.19.19.17.19.
Значит, чтобы получить текущее значение бактуна, катуна, туна, винала и кина, нам нужно разделить майянские дни сначала на 144000 (получим бактун), затем остаток от деления разделим на 7200 (получим катун), затем следующий остаток делим на 360 (получим тун), далее очередной остаток снова делим на 18 (винал), а последний остаток даст нам кин.

На Python все гораздо проще, нежели на словах:
d = М
result = []
for i in (144000, 7200, 360, 20, 1):
    t, d = divmod(d, i)
    result.append(t)

где М — ранее вычисленные майянские дни.

В итоге получим список, содержащий все нужные нам величины длинного счёта.

Ещё одно замечание. Так как найти живого представителя древнего народа майя, который бы до сих пор пользовался календарём своих предков, не представляется возможным, остаётся загадкой, как выражается бактун в период смены эр. Если эра начинается с нулевого бактуна, то весьма очевидно, что началом новой эры будет число 0.0.0.0.0. Но якобы майя избегали полностью нулевой даты, поэтому предположительно выражали начало новой эры как 13.0.0.0.0. Далее же не понятно, как выглядит следующий день новой эры — 13.0.0.0.1 или же 0.0.0.0.1. Разное представление на вычисление даты абсолютно не влияет, так что пойдём дальше.

Возьмёмся за цолькин. Цолькин состоит из двух частей — номера дня по 13-дневному циклу и названия дня по 20-дневному циклу. Назовём их T2 и T1 (местами я их меняю чисто из удобства, не обращайте внимания).

Следовательно,
T1 = (M + 19) % 20
T2 = (M + 3) % 13 + 1

где 3 и 19 — константы, означающие, что начало циклов цолькина не совпадало с началом майянской эры.
Следовательно, пусть кортеж имён дней цолькина будет
t1 = ("Imix'", "Ik'", "Ak'b'al", "K'an", "Chikchan", "Kimi", "Manik'", "Lamat", "Muluk", "Ok", "Chuwen", "Eb'", "B'en", "Ix", "Men", "K'ib'", "Kab'an", "Etz'nab'", "Kawak", "Ajaw")

тогда имя дня
T1s = t1[T1]


Теперь настал черёд и хааба.
С ним тоже всё достаточно просто. Пусть день месяца хааба будет H2, а сам месяц H1 (меняю местами для простоты вычисления).
Отсюда
H1, H2 = divmod((M + 348) % 365, 20)

где константа 348, как и в случае с цолькином, означает, что начало хааба не совпадало с началом эры.
И, по знакомой схеме, пусть имеем кортеж имён месяцев хааба
h1 = ("Pop", "Wo", "Sip", "Sotz'", "Tzek", "Xul", "Yaxk'", "Mol", "Ch'en", "Yax", "Sac", "Keh", "Mak", "K'ank'in", "Muwan", "Pax", "K'ayab'", "Kumk'u", "Wayeb'")

то название месяца
H1s = h1[H1]


Для полноты картины осталось вычислить владыку ночи. Проще простого:
G = (M + 8) % 9 + 1


Собственно всё это и делает моя программа, исходный код которой доступен по адресу https://bitbucket.org/mystic-mirage/mayanc (можно забрать git-ом по адресу git@bitbucket.org:mystic-mirage/mayanc.git)

Вот параметры командной строки, которые принимает программа:
-d <дата грегорианского календаря>, по-умолчанию — текущая дата;
-g <входной формат даты>, по-умолчанию '%Y-%m-%d' — параметр принимает все спецификаторы доступные в функции strptime() языка Python, но важны только год, месяц и день;
-f <выходной формат даты>, по-умолчанию '%C, %Z %H',
возможные спецификаторы:
%b — бактун,
%k — катун,
%t — тун,
%w — винал,
%i — кин,
%z1 — числовое значение названия дня цолькина (20-дневный цикл),
%z2 — номер дня цолькина (13-дневный цикл),
%z3 — название дня цолькина (20-дневный цикл),
%h1 — числовое значение месяца хааба,
%h2 — день месяца хааба,
%h3 — месяц хааба,
%l — номер владыки ночи,
%L — владыка ночи,
%C — длинный счёт (эквивалентно %b.%k.%t.%w.%i),
%Z — цолькин (эквивалентно %z2 %z3),
%H — хааб (эквивалентно %h2 %h3);
-c <корреляция> — обозначает применяемую корреляцию, может принимать любое значение, а так же могут быть указаны константы: gmt и tl, по-умолчанию — gmt, т. е. 584283;
-s <сценарий> — вариант интерпретации бактуна в период смены эр, по-умолчанию 1,
возможные значения:
1 — 13.0.0.0.0, но 0.0.0.0.1,
2 — 13.0.0.0.0 и 13.0.0.0.1,
3 — 0.0.0.0.0 и 0.0.0.0.1;
--gmt — эквивалентно -с gmt;
--tl — эквивалентно -c tl;
--baktun — эквивалентно -f '%b';
--katun — эквивалентно -f '%k';
--tun — эквивалентно -f '%t';
--winal — эквивалентно -f '%w';
--kin — эквивалентно -f '%i';
--tzol1 — эквивалентно -f '%t1';
--tzol2 — эквивалентно -f '%t2';
--tzol3 — эквивалентно -f '%t3';
--haab1 — эквивалентно -f '%h1';
--haab2 — эквивалентно -f '%h2';
--haab3 — эквивалентно -f '%h3';
--lord1 — эквивалентно -f '%l';
--lord2 — эквивалентно -f '%L';
--long — эквивалентно -f '%C' либо -f '%b.%k.%t.%w.%i';
--tzol — эквивалентно -f '%Z' либо -f '%z2 %z3';
--haab — эквивалентно -f '%H' либо -f '%h2 %h3';
--bc — обозначает, что исходная григорианская дата находится во временном отрезке до нашей эры, т. е. комбинация параметров -d 3114-08-11 --bc обозначает, что исходная дата — 11 августа 3114 года до нашей эры;
--no-l10n — не использовать локализированные названия.

Примечание. Добавление ключа --bc весьма усложнило код, в частности пришлось немного переписать распознавание даты по заданному формату (из-за того, что 1 год до нашей эры внезапно оказался високосным) и дополнить вычисление майянских дней. Зато теперь входным параметром может быть любая дата в диапазоне с 1 января 9999 года до н. э. — по 31 декабря 9999 года н. э.

Программу можно использовать не только из командной строки, но и как модуль для импорта:
from mayanc import *


Доступны такие функции:

todaydatetuple() — возвращает кортеж, содержащий текущую дату по григорианскому летосчислению (год, месяц, день), используется для других функций и простому пользователю по большему счёту бесполезна;
getmayandays(g_tuple = todaydatetuple(), cor = 584283, bc = False) —принимает кортеж даты (год, месяц, день), значение корреляции, флаг эры (н. э. — False, до н. э. —True) и возвращает майянские дни;
getlongcount(m_days, scenario = 1) — принимает майянские дни и тип сценария, а возвращает кортеж со значениями длинного счёта (бактун, катун, тун, винал, кин);
gettzolkin(m_days) — принимает майянские дни и возвращает кортеж состоящий со значениями 20- и 13-дневного циклов цолькина;
gethaab(m_days) — принимает майянские дни и возвращает кортеж со значениями месяца и числа хааба;
getlord(m_days) — принимает майянские дни и возвращает порядковый номер владыки ночи.

Так же есть такие кортежи:
tzolkinlist — содержит названия дней по 20-дневному циклу цолькина;
haablist — содержит названия месяцев хааба;
lordlist — содержит имена владык ночи, но т. к. они не известны, кортеж содержит обозначений (G1—G9);

Ещё есть такие константы:
gmt = 584283
tl = 584285

default_cor = gmt
default_fmt = '%C, %Z %H', что в сущности является эквивалентным такому набору спецификаторов — '%b.%k.%t.%w.%i, %z2 %z3 %h2 %h3'
default_sce = 1

Скрипт можно интегрировать с conky. Собственно для этого он и писался.
Теги:
Хабы:
+70
Комментарии 52
Комментарии Комментарии 52

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн