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-count a 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.

  • daypart one of three values before-sunrise(), daylight() or after-sunset(), to specify how the date will be converted into calendars in which days are sunset-to-sunset. Default is daylight().

  • locale a 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:

  • ☾ or U+263E before sunrise,

  • ☼ or U+263C during daylight,

  • ☽ or U+263D after 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

Date::Maya

DateTime::Calendar::Mayan

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.

Date::Calendar::MayaAztec v0.1.0

conversions from/to the Maya calendar and from/to the Aztec calendar

Authors

  • Jean Forget

License

Artistic-2.0

Dependencies

Date::Calendar::Strftime

Test Dependencies

Provides

  • Date::Calendar::Aztec
  • Date::Calendar::Aztec::Common
  • Date::Calendar::Aztec::Cortes
  • Date::Calendar::Aztec::Names
  • Date::Calendar::Maya
  • Date::Calendar::Maya::Astronomical
  • Date::Calendar::Maya::Common
  • Date::Calendar::Maya::Names
  • Date::Calendar::Maya::Spinden
  • Date::Calendar::MayaAztec

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.