Maya
NAME
Date::Calendar::Maya - conversions from/to the Maya calendar
SYNOPSIS
use Date::Calendar::Maya;
my Date $d-greg .= new(2020, 6, 20);
my Date::Calendar::Maya $d-maya .= new-from-date($d-greg);
say "{.tzolkin} {.haab} {.long-count}" with $d-maya;
# --> 12 Etznab 1 Tzec 13.0.7.10.18
$d-maya.locale = 'en';
say "{.tzolkin} {.haab}" with $d-maya;
# --> 12 Flint 1 Skull
Conversion while paying attention to sun rise and sun set:
use Date::Calendar::Strftime;
use Date::Calendar::Gregorian;
use Date::Calendar::Maya;
my Date::Calendar::Gregorian $d-gr;
my Date::Calendar::Maya $d-ma;
$d-gr .= new('2024-11-13', daypart => before-sunrise());
$d-ma .= new-from-date($d-gr);
say $d-ma.strftime("%F %V %A %e %B");
# --> "13.0.12.1.5 7 Chicchan 7 Ceh"
$d-gr .= new('2024-11-13', daypart => daylight());
$d-ma .= new-from-date($d-gr);
say $d-ma.strftime("%F %V %A %e %B");
# --> "13.0.12.1.5 7 Chicchan 8 Ceh"
$d-gr .= new('2024-11-13', daypart => after-sunset());
$d-ma .= new-from-date($d-gr);
say $d-ma.strftime("%F %V %A %e %B");
# --> "13.0.12.1.5 8 Cimi Ceh"
DESCRIPTION
Date::Calendar::Maya is a class which implements the Maya calendars (long count, Haab and Tzolkin).
This class uses the Goodman-Martinez-Thompson correlation. Other classes use the Spinden correlation or what is named "Astronomical" on the website http://research.famsi.org/date_mayaLC.php.
Mayas used three different calendars, the Long Count, the civil calendar or "Haab" and the clerical calendar or "Tzolkin".
The civil calendar is organized like other calendars, with days grouped in months grouped in years. The difference with other calendars is that the months last 20 days each, not around 30, and there are 18 months, not 12. Days are numbered 0 to 19, not 1 to 20. In theory months are not numbered, but in this module they are, for convenience reasons. In addition, there are 5 additional days (uayeb), but no leap days are defined.
A last difference with other calendars is that years are not numbered.
The clerical calendar consists of two simultaneous cycles, the first one with numbers 1 to 13, the second one with 20 names. This gives a clerical year of 260 days. As for the civil calendar, the 20 names are numbered for convenience reasons.
The long count consists of five embedded cycles:
kin or day
uinal, 1 uinal = 20 days
tun, 1 tun = 18 uinals
katun, 1 katun = 20 tuns
baktun, 1 baktun = 20 katuns
The uinal can be considered as a month, its duration is the same as the Haab month. The tun is a bit shorter than a solar year, 360 days instead of 365.24.
According to Reingold and Dershowitz, there is definitive evidence that the definition of Haab days and the definition of Tzolkin days differ. Yet, they do not know which are the exact definitions for the days. They suppose that Haab days are sunrise-to-sunrise and that Tzolkin days are sunset-to-sunset. No information is given for long-count days. So in this module, I use the following definitions for days:
Haab days are sunrise to sunrise
Tzolkin days are sunset to sunset
Long count days are midnight to midnight.
METHODS
Object Creation
new (long count)
Build a Maya date by giving a string containing the long count. The method accepts three keyword parameters:
long-counta string built of 5 numbers in dotted notation. These numbers are the components of the long count, baktun, katun, tun, uinal and kin. Each one is in the 0..19 range, except the uinal component which is in the 0..17 range.daypartone of three valuesbefore-sunrise(),daylight()orafter-sunset(), to specify how the date will be converted into calendars in which days are sunset-to-sunset. Default isdaylight().localea string giving the language in which the names are displayed. For the moment, you can use'yua'for the Yucatec language,'en'for the English language and'fr'for a partial support of the French language.
use Date::Calendar::Strftime;
use Date::Calendar::Maya;
my Date::Calendar::Maya $d-maya .= new(long-count => '13.0.7.12.15'
, daypart => after-sunset()
, locale => 'yua');
new (calendar round)
Maya dates can be created by providing the Haab and Tzolkin numerical values. You can use English keywords or Yucatec keywords. Here is the equivalence between them.
month haab-index
day haab-number
clerical-index tzolkin-index
clerical-number tzolkin-number
Since the calendar round values cannot determine a unique date, you
should add a reference date (from the core Date class or from any
Class::Calendar::xxx class), tagged with a relationship
before, on-or-before, after, on-or-after or nearest.
The reason why is explained in the Issues chapter,
Calendar Round Rollover subchapter below.
By default, the new method will use:
nearest => Date.today,
In addition, you can provide the optional parameters locale and
daypart. By default, they will be 'yua' for Yucatec and
daylight().
use Date::Calendar::Strftime;
use Date::Calendar::Maya;
my Date::Calendar::Maya $d-maya1 .= new(month => 6 # for Xul
, day => 19
, clerical-number => 11
, clerical-index => 16 # For Cib
, daypart => daylight()
, locale => 'yua'
, on-or-after => Date.new('2001-01-01'));
say $d-maya1;
# --> "13.0.7.12.16"
my Date::Calendar::Maya $d-maya2 .= new(haab-index => 12 # for Ceh
, haab-number => 8
, tzolkin-number => 8
, tzolkin-index => 6 # For Cimi
, daypart => after-sunset()
, locale => 'yua'
, nearest => Date.new('2020-08-01'));
say $d-maya2;
# --> "13.0.12.1.5"
new-from-date
Build an Maya date by cloning an object from another class. This other
class can be the core class Date or any Date::Calendar::xxx
class with a daycount method and hopefully a daypart method.
If the origin instance has a locale attribute, it is not copied to
the result instance.
use Date::Calendar::Strftime;
use Date::Calendar::Gregorian;
use Date::Calendar::Maya;
my Date::Calendar::Gregorian $d-gr;
my Date::Calendar::Maya $d-ma;
$d-gr .= new("2024-11-13", daypart => after-sunset(), locale => 'fr');
$d-ma .= new-from-date($d-gr);
$d-ma.locale = $d-gr.locale;
say $d-gr.strftime("%A %e %B %Y");
# --> "mercredi 13 novembre 2024"
say $d-ma.strftime("%F %e %B %V %A");
# --> "13.0.12.1.5 8 Ceh 8 Mort"
new-from-daycount
Build an Maya date from the Modified Julian Day number and from the
daypart parameter (optional, defaults do daylight()).
Attribute getters
month
The numeric equivalent of the Haab name.
For strftime, use the %m specifier.
month-name, haab-name
The name part of the civil calendar (Haab). Its value depends on the
value of the locale attribute.
For strftime, use the %B specifier.
day
The numeric part of the civil calendar (Haab), 0 to 19.
For strftime, use the %d or %e specifier.
haab
A string merging the numeric part and the name part of the civil
calendar (Haab). Its value depends on the value of the locale
attribute.
No single strftime specifier, you have to mix %B with %d or
%e.
clerical-number, tzolkin-number
The numeric part of the clerical calendar (Tzolkin).
For strftime, use the %V specifier.
clerical-name, tzolkin-name
The name part of the clerical calendar (Tzolkin). Its value depends on
the value of the locale attribute.
For strftime, use the %A specifier.
clerical-index, tzolkin-index
The numeric equivalent of the name part of the clerical calendar (Tzolkin), 1 to 20.
For strftime, use the %u specifier.
tzolkin
A string merging the numeric part and the name part of the clerical
calendar (Tzolkin). Its value depends on the value of the locale
attribute.
No single strftime specifier, you have to mix %V with %u.
year-bearer-number, year-bearer-index, year-bearer-name, year-bearer
The year bearer is the Tzolkin date for the first day of the current Haab year, that is, 0 Pop. The year bearer is some kind of name for the Haab year, which is unnumbered. Yet it cannot define unambiguously the year, since it cycles every 52 Haab years (a calendar round).
These four methods define the year bearer. Their names are similar to
the clerical-xxx and the tzolkin-xxx methods, because the
year bearer is a Tzolkin date.
For strftime, use the %Y of %G specifier to print the year
bearer (number and name).
gist, long-count
The long count in dotted notation.
daycount
The MJD (Modified Julian Date) number for the date.
daypart
A number indicating which part of the day. This number should be filled and compared with the following subroutines, with self-documenting names:
before-sunrise()
daylight()
after-sunset()
locale
The abbreviation of the language used for names. Actually, this attribute is read-write. You can create a date object with a first locale and then change it to another locale.
For the moment, the allowed values are 'yua' for Yucatec, a Mayan
language, 'en' for English and 'fr' for French (partial, only
Tzolkin names are translated into French, Haab names are in Yucatec).
strftime
This method gives a string containing several attributes listed above. It is similar to the homonymous function in other languages. See the strftime Specifiers paragraph below.
Other Methods
to-date
Clones the date into a core class Date object or some
Date::Calendar::xxx compatible calendar class. The target class
name is given as a positional parameter. This parameter is optional,
the default value is "Date" for the Gregorian calendar.
To convert a date from a calendar to another, you have two conversion styles, a "push" conversion and a "pull" conversion. For example, while converting "13.0.7.6.11" to the French Revolutionary calendar, you can code:
use Date::Calendar::Maya;
use Date::Calendar::FrenchRevolutionary;
my Date::Calendar::Maya $d-orig;
my Date::Calendar::FrenchRevolutionary $d-dest-push;
my Date::Calendar::FrenchRevolutionary $d-dest-pull;
$d-orig .= new(long-count => '13.0.7.6.11');
$d-dest-push = $d-orig.to-date("Date::Calendar::FrenchRevolutionary");
$d-dest-pull .= new-from-date($d-orig);
say $d-orig, ' ', $d-dest-push, ' ', $d-dest-pull;
# --> "13.0.7.6.11 0228-07-06 0228-07-06"
When converting from the core class Date, use the pull style.
When converting to the core class Date, use the push style. When
converting from any class other than the core class Date to any
other class other than the core class Date, use the style you
prefer. This includes the class Date::Calendar::Gregorian, a child
class to the core class Date.
Even if both classes use a locale attribute, when a date is created
by the conversion of another date, it is created with the default
locale. If you want the locale to be transmitted in the conversion,
you should add this line:
$d-dest-pull.locale = $d-orig.locale;
strftime Specifiers
Designer's Notes
The Maya calendar is not like the others, based on year-month-day
triplets. So defining which data will be printed by which strftime
specifier is not obvious. Let us see what can be done with the
principle of least surprise.
At least, the common calendar (Haab) is based on month-day pairs. And
the months have an unambiguous numeric representation. So we can
easily define what will be printed by %B, %d, %e, %f and
%m. The tzolkin names (Imix, Ik...) run through a cycle, just as
the week days (Monday, Tuesday...), so it is natural to assimilate
both notions, even if the cycle lengths are different: 20 in the first
case, 7 in the latter case. So specifiers %A and %u are cared
for.
That is all for the obvious equivalences. Now, we can define other
specifiers by shoe-horning a Gregorian concept into them. For example
the %F specifier. Its basic definition is "a short-hand for
%Y-%m-%d", but it can be described as "a specifier containing all
the values to uniquely identify the date". The equivalent for the Maya
calendar would be the Long Count. So the %F specifier will print
the long count in dotted notation.
And the %V specifier? It represents the week number for the
Gregorian calendar, or how many 7-day cycles have elapsed since the
beginning of the year. Translated into the Maya class, it would give
the number of 20-name cycles since the beginning of the year. This is
not interesting for the Maya calendar,
because a Tzolkin 20-name cycle coincidates with a Haab 20-day month.
Another way to describe the %V specifier is "the number which is
usually printed associated to %u (in the ISO date format)". Since
%u gives the Tzolkin index (the numeric form of the Tzolkin name), %V should give
the Tzolkin number.
What about the year numbers %Y and %G? It could be the long
count truncated to baktun-katun-tun. Which is not interesting. A
better idea consists of describing these specifiers as "the specifier
which keeps the same value from 1st January to 31st December". In the
Maya calendar, which notion keeps the same value from 0 Pop until 19
Cumku? The year bearer which, therefore, can uniquely identify a year,
within some limits. More precisely, within a calendar round (52
years), the year bearer is a unique identifier for the Haab year. So
the %Y specifier will print the year bearer. On the other hand,
identifying the year with its year bearer is flawed with a rollover
problem similar to the Y2K bug, except that it occurs every 52 years
instead of every 100 years. So it may be better to associate the year
bearer with the %y specifier, which can be defined as the
"Y2K-flawed year specifier".
Specifiers
- %A
The Tzolkin name, similar to the name of the day of week.
- %B
The Haab name, similar to a month name.
- %d
The Haab number, which can be seen as the numeric form of the day of the month (range 00 to 19).
- %e
Like %d, the Haab number or day of the month as a decimal number,
but a leading zero is replaced by a space.
- %f
The numeric form of the Haab name, or month as a decimal number (1 to
19). Unlike %m, a leading zero is replaced by a space.
- %F
The long count, in dotted notation.
- %G
The year bearer.
- %j
The day of the year as a decimal number (range 000 to 364).
- %m
The numeric form of the Haab name, or the month, as a two-digit decimal number (range 01 to 12), including a leading zero if necessary.
- %n
A newline character.
- %Ep
Gives a 1-char string representing the day part:
☾orU+263Ebefore sunrise,☼orU+263Cduring daylight,☽orU+263Dafter sunset.
Rationale: in C or in other programming languages, when strftime
deals with a date-time object, the day is split into two parts, before
noon and after noon. The %p specifier reflects this by giving a
"AM" or "PM" string.
The 3-part splitting in the Date::Calendar::xxx may be
considered as an alternate splitting of a day. To reflect this in
strftime, we use an alternate version of %p, therefore %Ep.
- %t
A tab character.
- %u
The Tzolkin index, that is the 1..20 numeric equivalent of the Tzolkin name.
- %V
The Tzolkin number.
- %Y
The year bearer.
- %%
A literal `%' character.
Modifiers
A complete strftime specifier consists of:
A percent sign,
An optional minus sign, to indicate on which side the padding occurs. If the minus sign is present, the value is aligned to the left and the padding spaces are added to the right. If it is not there, the value is aligned to the right and the padding chars (spaces or zeroes) are added to the left.
An optional zero digit, to choose the padding char for right-aligned values. If the zero char is present, padding is done with zeroes. Else, it is done wih spaces.
An optional length, which specifies the minimum length of the result substring.
An optional
"E"or"O"modifier. On some older UNIX system, these were used to give the extended or localized version of the date attribute. Here, these"E"and"O"modifiers are ignored.
ISSUES
Mayan or Maya?
According to http://www.famsi.org/research/vanstone/2012/faq.html#mayan, the word "Mayan" applies only to the family of languages used by the Mayas. In all other cases, including the calendars, we should use the word "Maya".
About the utility module Date::Calendar::Maya::Names: this module
contains Mayan names. Yet, I have chosen not to call it
Date::Calendar::Mayan::Names for two reasons: first, that would
create two nearly similar subdirectories Maya and Mayan, second
this module contains also English and French names, so this is not a
module of Mayan names, it is a module of names for the Maya
calendar.
Day Definition
According to Reingold and Dershowitz, we suppose that actually the Haab days are sunrise to sunrise and that the Tzolkin days are sunset to sunset. But this is only a supposition. On the other hand, Reingold and Dershowitz do not give any supposition, much less any definite information, about the beginning of loung count days.
As already written above, this class use the following definitions of days:
Haab days are sunrise to sunrise
Tzolkin days are sunset to sunset
Long count days are midnight to midnight.
Baktun Numbering
The long count uses base-20 numbering, with the exception of the uinal number, which uses the 0..17 range instead of 0..19. But some people think that there is another exception with the baktun number, which uses a cycle ending with number 13. See Claus Tøndering's Calendar FAQ.
The belief that baktun 13 is a special one may come from the fact that for end-of-the-worldists in the late XXth century and in the early XXIst century, the switch from 12 to 13 would occur during their lifetimes. Other considerations point at the special significance of number 13 in the Maya civilization. Actually, as described in Wikipedia (https://en.wikipedia.org/wiki/Maya_calendar#Long_Count and https://en.wikipedia.org/wiki/Mesoamerican_Long_Count_calendar#2012_and_the_Long_Count) archeologists have found carved long count dates beyond the 13.0.0.0.0 date, which means that in the mind of the carver, the world would not end at 13.0.0.0.0.
This module assumes that baktun 13 has no special significance and that baktuns are numbered until 19. The higher-order cycles, piktun, calabtun, kinchiltun and alautun are not implemented.
Long Count Rollover
As a consequence of the previous paragraph, the calendar rolls over every 20 baktuns, that is, every 7885 years. The next rollover date is 4772-10-12. So there is time before a fix is needed.
Calendar Round Rollover
For convenience, you can use a new method with Haab and Tzolkin
values, just like it is done in the D::C::Aztec class with
xiuhpohualli and tonalpohualli values. By combining the Haab (civil
calendar) with the Tzolkin (clerical calendar), we get different
combinations for about 52 years. This period is called the "calendar
round". So when given an Maya date with the four values (Haab number
and name, Tzolkin number and name), you cannot define a unique
Gregorian date equivalent to this Maya date. The Gregorian date 52
years later (or 104, or 156) and the Gregorian date 52 years earlier
(or 104 or...) also correspond to this Maya date.
For this reason, when using this kind of new method, Maya dates are
created with a reference date from another calendar, so the module
will compute which is the first Maya date on or after the reference
date and with the requested month, name, clerical index and clerical
number (or "on or before the reference date", or "nearest to the
reference date", etc). This allows the module to compute an attribute
daycount, which will be used when computing the long count and when
converting the Maya date to another calendar.
French Translation
I have found the French translation for Tzolkin names, but not for Haab names. So while using the French locale, Haab names are given with the default locale, Yucatec.
Year Bearer For Additional Days
According to Reingold and Dershowitz, the year bearer is not defined for additional days (uayeb). On the other hand, the website http://research.famsi.org/date_mayaLC.php displays the year bearer for additional days. I have taken the programmer-friendly option of computing the year bearer for additional days as for the normal days.
Security issues
As explained in the Date::Calendar::Strftime documentation, please
ensure that format-string passed to strftime comes from a trusted
source. Failing that, the untrusted source can include a outrageous
length in a strftime specifier and this will drain your PC's RAM
very fast.
Relations with :ver<0.0.x> classes and with core class Date
Version 0.1.0 (and API 1) was introduced to ease the conversions with
between calendars in which the day is defined as sunset-to-sunset and
calendars in which the day is defined as midhnight-to-midnight. If all
Date::Calendar::xxx classes use version 0.1.x and API 1, the
conversions will be correct. But if some Date::Calendar::xxx
classes use version 0.0.x and API 0, there might be problems.
A date from a 0.0.x class has no daypart attribute. But when "seen"
from a 0.1.x class, the 0.0.x date seems to have a daypart
attribute equal to daylight. When converted from a 0.1.x class to a
0.0.x class, the date may just shift from after-sunset (or
before-sunrise) to daylight, or it may shift to the daylight
part of the prior (or next) date. This means that a roundtrip with
cascade conversions may give the starting date, or it may give the
date prior or after the starting date.
If you install <Date::Calendar::MayaAztec:ver<0.1.0>>, why would
you refrain from upgrading other Date::Calendar::xxxx classes?
So actually, this issue applies mainly to the core class Date,
because you may prefer avoiding the installation of
Date::Calendar::Gregorian.
Time
This module and the Date::Calendar::xxx associated modules are
still date modules, they are not date-time modules. The user has to
give the daypart attribute as a value among before-sunrise,
daylight or after-sunset. There is no provision to give a HHMMSS
time and convert it to a daypart parameter.
SEE ALSO
Raku Software
Date::Calendar::Strftime or https://github.com/jforget/raku-Date-Calendar-Strftime
Date::Calendar::Gregorian or https://github.com/jforget/raku-Date-Calendar-Gregorian
Date::Calendar::Julian or https://github.com/jforget/raku-Date-Calendar-Julian
Date::Calendar::Hebrew or https://github.com/jforget/raku-Date-Calendar-Hebrew
Date::Calendar::Hijri or https://github.com/jforget/raku-Date-Calendar-Hijri
Date::Calendar::Persian or https://github.com/jforget/raku-Date-Calendar-Persian
Date::Calendar::CopticEthiopic or https://github.com/jforget/raku-Date-Calendar-CopticEthiopic
Date::Calendar::Bahai or https://github.com/jforget/raku-Date-Calendar-Bahai
Date::Calendar::FrenchRevolutionary or https://github.com/jforget/raku-Date-Calendar-FrenchRevolutionary
Perl 5 Software
Other Software
calendar/cal-mayan.el in Emacs
CALENDRICA 4.0 -- Common Lisp, which can be download in the "Resources" section of https://www.cambridge.org/us/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition?format=PB&isbn=9781107683167
Books
Calendrical Calculations (Third or Fourth Edition) by Nachum Dershowitz and Edward M. Reingold, Cambridge University Press, see http://www.calendarists.com or https://www.cambridge.org/us/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition?format=PB&isbn=9781107683167. ISBN 978-0-521-70238-6 for the third edition.
La saga des calendriers, by Jean Lefort, published by Belin (Pour la Science), ISBN 2-90929-003-5 See https://www.belin-editeur.com/la-saga-des-calendriers (website no longer responding).
Histoire comparée des numérations écrites by Geneviève Guitel, published by Flammarion (Nouvelle bibliothèque scientifique), ISBN 2-08-21114-0
Internet
https://en.wikipedia.org/wiki/Maya_calendar
https://www.tondering.dk/claus/cal/maya.php
https://www.timeanddate.com/calendar/mayan.html
http://research.famsi.org/date_mayaLC.php
AUTHOR
Jean Forget <J2N-FORGET at orange dot fr>
COPYRIGHT AND LICENSE
Copyright (c) 2020, 2023, 2024 Jean Forget
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.