Mayan calendar
You are encouraged to solve this task according to the task description, using any language you may know.
The ancient Maya people had two somewhat distinct calendar systems.
In somewhat simplified terms, one is a cyclical calendar known as The Calendar Round, that meshes several sacred and civil cycles; the other is an offset calendar known as The Long Count, similar in many ways to the Gregorian calendar.
The Calendar Round
The Calendar Round has several intermeshing sacred and civil cycles that uniquely identify a specific date in an approximately 52 year cycle.
The Tzolk’in
The sacred cycle in the Mayan calendar round was called the Tzolk’in. The Tzolk'in has a cycle of 20 day names:
Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw
Intermeshed with the named days, the Tzolk’in has a cycle of 13 numbered days; 1 through 13. Every day has both a number and a name that repeat in a 260 day cycle.
For example:
1 Imix’ 2 Ik’ 3 Ak’bal ... 11 Chuwen 12 Eb 13 Ben 1 Hix 2 Men 3 K’ib’ ... and so on.
The Haab’
The Mayan civil calendar is called the Haab’. This calendar has 365 days per year, and is sometimes called the ‘vague year.’ It is substantially the same as our year, but does not make leap year adjustments, so over long periods of time, gets out of synchronization with the seasons. It consists of 18 months with 20 days each, and the end of the year, a special month of only 5 days, giving a total of 365. The 5 days of the month of Wayeb’ (the last month), are usually considered to be a time of bad luck.
Each month in the Haab’ has a name. The Mayan names for the civil months are:
Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh Mak K’ank’in Muwan Pax K’ayab Kumk’u Wayeb’ (Short, "unlucky" month)
The months function very much like ours do. That is, for any given month we count through all the days of that month, and then move on to the next month.
Normally, the day 1 Pop is considered the first day of the civil year, just as 1 January is the first day of our year. In 2019, 1 Pop falls on April 2nd. But, because of the leap year in 2020, 1 Pop falls on April 1st in the years 2020-2023.
The only really unusual aspect of the Haab’ calendar is that, although there are 20 (or 5) days in each month, the last day of the month is not called the 20th (5th). Instead, the last day of the month is referred to as the ‘seating,’ or ‘putting in place,’ of the next month. (Much like how in our culture, December 24th is Christmas Eve and December 31st is 'New-Years Eve'.) In the language of the ancient Maya, the word for seating was chum, So you might have:
... 18 Pop (18th day of the first month) 19 Pop (19th day of the first month) Chum Wo’ (20th day of the first month) 1 Wo’ (1st day of the second month) ... and so on.
Dates for any particular day are a combination of the Tzolk’in sacred date, and Haab’ civil date. When put together we get the “Calendar Round.”
Calendar Round dates always have two numbers and two names, and they are always written in the same order:
(1) the day number in the Tzolk’in (2) the day name in the Tzolk’in (3) the day of the month in the Haab’ (4) the month name in the Haab’
A calendar round is a repeating cycle with a period of just short of 52 Gregorian calendar years. To be precise: it is 52 x 365 days. (No leap days)
Lords of the Night
A third cycle of nine days honored the nine Lords of the Night; nine deities that were associated with each day in turn. The names of the nine deities are lost; they are now commonly referred to as G1 through G9. The Lord of the Night may or may not be included in a Mayan date, if it is, it is typically just the appropriate G(x) at the end.
The Long Count
Mayans had a separate independent way of measuring time that did not run in cycles. (At least, not on normal human scales.) Instead, much like our yearly calendar, each day just gets a little further from the starting point. For the ancient Maya, the starting point was the ‘creation date’ of the current world. This date corresponds to our date of August 11, 3114 B.C. Dates are calculated by measuring how many days have transpired since this starting date; This is called “The Long Count.” Rather than just an absolute count of days, the long count is broken up into unit blocks, much like our calendar has months, years, decades and centuries.
The basic unit is a k’in - one day. A 20 day month is a winal. 18 winal (360 days) is a tun - sometimes referred to as a short year. 20 short years (tun) is a k’atun 20 k’atun is a bak’tun
There are longer units too:
Piktun == 20 Bak’tun (8,000 short years) Kalabtun == 20 Piktun (160,000 short years) Kinchiltun == 20 Kalabtun (3,200,000 short years)
For the most part, the Maya only used the blocks of time up to the bak’tun. One bak’tun is around 394 years, much more than a human life span, so that was all they usually needed to describe dates in this era, or this world. It is worth noting, the two calendars working together allow much more accurate and reliable notation for dates than is available in many other calendar systems; mostly due to the pragmatic choice to make the calendar simply track days, rather than trying to make it align with seasons and/or try to conflate it with the notion of time.
Mayan Date correlations
There is some controversy over finding a correlation point between the Gregorian and Mayan calendars. The Gregorian calendar is full of jumps and skips to keep the calendar aligned with the seasons so is much more difficult to work with. The most commonly used correlation factor is The GMT: 584283. Julian 584283 is a day count corresponding Mon, Aug 11, 3114 BCE in the Gregorian calendar, and the final day in the last Mayan long count cycle: 13.0.0.0.0 which is referred to as "the day of creation" in the Mayan calendar. There is nothing in known Mayan writing or history that suggests that a long count "cycle" resets every 13 bak’tun. Judging by their other practices, it would make much more sense for it to reset at 20, if at all.
The reason there was much interest at all, outside historical scholars, in the Mayan calendar is that the long count recently (relatively speaking) rolled over to 13.0.0.0.0 (the same as the historic day of creation Long Count date) on Fri, Dec 21, 2012 (using the most common GMT correlation factor), prompting conspiracy theorists to predict a cataclysmic "end-of-the-world" scenario.
Excerpts taken from, and recommended reading:
- From the website of the Foundation for the Advancement of Meso-America Studies, Inc.
Pitts, Mark. The complete Writing in Maya Glyphs Book 2 – Maya Numbers and the Maya Calendar. 2009. Accessed 2019-01-19.
http://www.famsi.org/research/pitts/MayaGlyphsBook2.pdf
The Task:
Write a reusable routine that takes a Gregorian date and returns the equivalent date in Mayan in the Calendar Round and the Long Count. At a minimum, use the GMT correlation. If desired, support other correlations.
Using the GMT correlation, the following Gregorian and Mayan dates are equivalent:
Dec 21, 2012 (Gregorian) 4 Ajaw 3 K’ank’in G9 (Calendar round) 13.0.0.0.0 (Long count)
Support looking up dates for at least 50 years before and after the Mayan Long Count 13 bak’tun rollover: Dec 21, 2012. (Will require taking into account Gregorian leap days.)
Show the output here, on this page, for at least the following dates:
(Note that these are in ISO-8601 format: YYYY-MM-DD. There is no requirement to use ISO-8601 format in your program, but if you differ, make a note of the expected format.)
2004-06-19 2012-12-18 2012-12-21 2019-01-19 2019-03-27 2020-02-29 2020-03-01
11l
V _DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
V _DAYS_BEFORE_MONTH = [-1]
V dbm = 0
L(dim) _DAYS_IN_MONTH[1..]
_DAYS_BEFORE_MONTH.append(dbm)
dbm += dim
F _days_before_year(year)
‘year -> number of days before January 1st of year.’
V y = year - 1
R y * 365 + y I/ 4 - y I/ 100 + y I/ 400
F _is_leap(year)
‘year -> 1 if leap year, else 0.’
R year % 4 == 0 & (year % 100 != 0 | year % 400 == 0)
F _days_before_month(year, month)
‘year, month -> number of days in year preceding first day of month.’
R :_DAYS_BEFORE_MONTH[month] + (month > 2 & _is_leap(year))
F _ymd2ord(year, month, day)
‘year, month, day -> ordinal, considering 01-Jan-0001 as day 1.’
R (_days_before_year(year) + _days_before_month(year, month) + day)
F g2m(date, gtm_correlation = 1B)
V correlation = I gtm_correlation {584283} E 584285
V long_count_days = [144000, 7200, 360, 20, 1]
V tzolkin_months = ["Imix'", "Ik'", "Ak'bal", "K'an", ‘Chikchan’, ‘Kimi’, "Manik'", ‘Lamat’, ‘Muluk’, ‘Ok’, ‘Chuwen’,
‘Eb’, ‘Ben’, ‘Hix’, ‘Men’, "K'ib'", ‘Kaban’, "Etz'nab'", ‘Kawak’, ‘Ajaw’]
V haad_months = [‘Pop’, "Wo'", ‘Sip’, "Sotz'", ‘Sek’, ‘Xul’, "Yaxk'in", ‘Mol’, "Ch'en", ‘Yax’, "Sak'", ‘Keh’, ‘Mak’,
"K'ank'in", ‘Muwan’, ‘Pax’, "K'ayab", "Kumk'u", "Wayeb'"]
V (year, month, day) = date.split(‘-’).map(Int)
V gregorian_days = _ymd2ord(year, month, day)
V julian_days = gregorian_days + 1721425
[Int] long_date
V remainder = julian_days - correlation
L(days) long_count_days
(V result, remainder) = divmod(remainder, days)
long_date.append(Int(result))
V long_date_str = (long_date.map(d -> ‘#02’.format(d))).join(‘.’)
V tzolkin_month = (julian_days + 16) % 20
V tzolkin_day = ((julian_days + 5) % 13) + 1
V haab_month = Int(((julian_days + 65) % 365) / 20)
V haab_day = ((julian_days + 65) % 365) % 20
V haab_day_str = I haab_day {String(haab_day)} E ‘Chum’
V lord_number = (julian_days - correlation) % 9
lord_number = I lord_number {lord_number} E 9
V round_date = tzolkin_day‘ ’tzolkin_months[tzolkin_month]‘ ’haab_day_str‘ ’haad_months[haab_month]‘ G’lord_number
R (long_date_str, round_date)
V dates = [‘2004-06-19’, ‘2012-12-18’, ‘2012-12-21’, ‘2019-01-19’, ‘2019-03-27’, ‘2020-02-29’, ‘2020-03-01’]
L(date) dates
V (long, round_date) = g2m(date)
print(date‘ ’long‘ ’round_date)
- Output:
2004-06-19 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 13.00.07.05.07 5 Manik' 15 K'ayab G8
C++
#include <chrono>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
const std::vector<std::string> Tzolkin = { "Imix'", "Ik'", "Ak'bal", "K'an", "Chikchan", "Kimi", "Manik'",
"Lamat", "Muluk", "Ok", "Chuwen", "Eb", "Ben", "Hix", "Men", "K'ib'", "Kaban", "Etz'nab'", "Kawak", "Ajaw" };
const std::vector<std::string> Haab = { "Pop", "Wo'", "Sip", "Sotz'", "Sek", "Xul", "Yaxk'in", "Mol",
"Ch'en", "Yax", "Sak'", "Keh", "Mak", "K'ank'in", "Muwan", "Pax", "K'ayab", "Kumk'u", "Wayeb'" };
int32_t positive_modulus(const int32_t& base, const int32_t& modulus) {
const int32_t result = base % modulus;
return ( result < 0 ) ? result + modulus : result;
}
std::chrono::sys_days create_date(const std::string& iso_date) {
const int year = std::stoi(iso_date.substr(0, 4));
const unsigned int month = std::stoi(iso_date.substr(5, 7));
const unsigned int day = std::stoi(iso_date.substr(8, 10));
std::chrono::year_month_day date{std::chrono::year{year}, std::chrono::month{month}, std::chrono::day{day}};
return std::chrono::sys_days(date);
}
const std::chrono::sys_days CREATION_TZOLKIN = create_date("2012-12-21");
const std::chrono::sys_days ZERO_HAAB = create_date("2019-04-02");
int32_t days_per_mayan_month(const std::string& month) {
return ( month == "Wayeb'" ) ? 5 : 20;
}
std::string tzolkin(const std::chrono::sys_days& gregorian) {
const int32_t days_between = ( gregorian - CREATION_TZOLKIN ).count();
int32_t remainder = positive_modulus(days_between, 13);
remainder += ( remainder <= 9 ) ? 4 : -9;
return std::to_string(remainder) + " " + Tzolkin[positive_modulus(days_between - 1, 20)];
}
std::string haab(const std::chrono::sys_days& gregorian) {
const int32_t days_between = ( gregorian - ZERO_HAAB ).count();
int32_t remainder = positive_modulus(days_between, 365);
const std::string month = Haab[positive_modulus(remainder + 1, 20)];
const int32_t day_of_month = remainder % 20 + 1;
return ( day_of_month < days_per_mayan_month(month) ) ?
std::to_string(day_of_month) + " " + month : "Chum " + month;
}
std::string long_count(const std::chrono::sys_days& gregorian) {
int32_t days_between = ( gregorian - CREATION_TZOLKIN ).count() + 13 * 360 * 400;
const int32_t baktun = positive_modulus(days_between, 360 * 400);
days_between = days_between % ( 360 * 400 );
const int32_t katun = days_between / ( 20 * 360 );
days_between = days_between % ( 20 * 360 );
const int32_t tun = days_between / 360;
days_between = days_between % 360;
const int32_t winal = days_between / 20;
const int32_t kin = days_between % 20;
std::string result = "";
for ( int32_t number : { baktun, katun, tun, winal, kin } ) {
std::string value = std::to_string(number) + ".";
result += ( number <= 9 ) ? "0" + value : value;
}
return result.substr(0, result.length() - 1);
}
std::string lords_of_the_night(const std::chrono::sys_days& gregorian) {
const int32_t days_between = ( gregorian - CREATION_TZOLKIN ).count();
const int32_t remainder = days_between % 9;
return "G" + std::to_string( ( remainder <= 0 ) ? remainder + 9 : remainder );
}
int main() {
const std::vector<std::string> iso_dates = { "2004-06-19", "2012-12-18", "2012-12-21", "2019-01-19",
"2019-03-27", "2020-02-29", "2020-03-01", "2071-05-16", "2020-02-02" };
std::cout << "Gregorian Long Count Tzolk'in Haab' Lords of the Night" << std::endl;
std::cout << "------------------------------------------------------------------------------" << std::endl;
for ( const std::string& iso_date : iso_dates ) {
const std::chrono::sys_days date = create_date(iso_date);
std::cout << std::left << std::setw(15) << iso_date << std::setw(19) << long_count(date)
<< std::setw(12) << tzolkin(date) << std::setw(18) << haab(date)
<< lords_of_the_night(date) << std::endl;
}
}
- Output:
Gregorian Long Count Tzolk'in Haab' Lords of the Night ------------------------------------------------------------------------------ 2004-06-19 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 13.00.07.05.07 5 Manik' 15 K'ayab G8 2071-05-16 13.02.19.04.10 1 Ok 18 Sip G9 2020-02-02 13.00.07.03.19 3 Kawak 7 Pax G7
Fortran
PROGRAM MAYA_DRIVER
IMPLICIT NONE
!
! Local variables
!
CHARACTER(80) :: haab_carry
CHARACTER(80) :: long_carry
CHARACTER(80) :: nightlord
CHARACTER(80) :: tzolkin_carry
INTEGER,DIMENSION(8) :: DAY, MONTH, YEAR
INTEGER :: INDEX
DATA YEAR /2071,2004,2012,2012,2019,2019,2020,2020/
DATA MONTH /5,6,12,12,1,3,2,3/
DATA DAY /16,19,18,21,19,27,29,01/
! 2071-05-16
! 2004-06-19
! 2012-12-18
! 2012-12-21
! 2019-01-19
! 2019-03-27
! 2020-02-29
! 2020-03-01
DO INDEX = 1,8
!
CALL MAYA_TIME(day(INDEX) , month(INDEX) , year(INDEX) , long_carry , haab_carry , tzolkin_carry , &
& nightlord)
WRITE(6,20)day(INDEX),month(INDEX),year(INDEX),TRIM(tzolkin_carry),TRIM(haab_carry),TRIM(long_carry),TRIM(nightlord)
20 FORMAT(1X,I0,'-',I0,'-',I0,T12,A,T24,A,T38,A,T58,A)
END DO
STOP
END PROGRAM MAYA_DRIVER
!
! SUBROUTINE MAYA_TIME
subroutine maya_time(day,month,year, long_carry,haab_carry, tzolkin_carry,nightlord)
implicit none
integer(kind=4), parameter :: startdate = 584283 ! Start of the Mayan Calendar in Julian days
integer(kind=4), parameter :: kin = 1
integer(kind=4), parameter :: winal = 20*kin
integer(kind=4), parameter :: tun = winal*18
integer(kind=4), parameter :: katun = tun*20
integer(kind=4), parameter :: baktun = katun*20
integer(kind=4), parameter :: piktun = baktun*20
integer(kind=4), parameter :: longcount = baktun*20
!
character(len=8), dimension(20) ,parameter :: tzolkin = &
["Imix' ", "Ik´ ", "Ak´bal ", "K´an ", "Chikchan", "Kimi ", &
"Manik´ ", "Lamat ", "Muluk ", "Ok ", "Chuwen ", "Eb ", &
"Ben ", "Hix ", "Men ", "K´ib´ ", "Kaban ", "Etz´nab´", &
"Kawak ", "Ajaw "]
character(len=8), dimension(19) ,parameter :: haab = &
["Pop ", "Wo´ ", "Sip ", "Sotz´ ", "Sek ", "Xul ", &
"Yaxk´in ", "Mol ", "Ch´en ", "Yax ", "Sak´ ", "Keh ", &
"Mak ", "K´ank´in", "Muwan ", "Pax ", "K´ayab ", "Kumk´u ", &
"Wayeb´ "]
character(len=20), dimension(9) ,parameter :: night_lords = &
["(G1) Xiuhtecuhtli ", & ! ("Turquoise/Year/Fire Lord")
"(G2) Tezcatlipoca ", & ! ("Smoking Mirror")
"(G3) Piltzintecuhtli", & ! ("Prince Lord")
"(G4) Centeotl ", & ! ("Maize God")
"(G5) Mictlantecuhtli", & ! ("Underworld Lord")
"(G6) Chalchiuhtlicue", & ! ("Jade Is Her Skirt")
"(G7) Tlazolteotl ", & ! ("Filth God[dess]")
"(G8) Tepeyollotl ", & ! ("Mountain Heart")
"(G9) Tlaloc " ] ! (Rain God)
integer(kind=4) :: day,month,year
intent(in) :: day,month,year
!
integer(kind=4) :: j,l, numdays, keptdays
integer(kind=4) :: kin_no, winal_no, tun_no, katun_no, baktun_no, longcount_no
character(*) :: haab_carry, nightlord, tzolkin_carry, long_carry
intent(inout) :: haab_carry, nightlord, tzolkin_carry, long_carry
integer :: mo,da
!
keptdays = julday(day,month,year) ! Get the Julian date for selected date
numdays = keptdays ! Keep for calcs later
! Adjust from the beginning
numdays = numdays-startdate ! Adjust the number of days from start of Mayan Calendar
if (numdays .ge. longcount)then ! We check if we have passed a longcount and need to adjust for a new start
longcount_no = numdays/longcount
print*, ' We have more than one longcount ',longcount_no
endif
!
! Calculate the longdate
baktun_no = numdays/baktun
numdays = numdays - (baktun_no*baktun) ! Decrement days down by the number of baktuns
katun_no = numdays/katun ! Get number of katuns
numdays = numdays - (katun_no*katun)
tun_no = numdays/tun
numdays = numdays-(tun_no*tun)
winal_no = numdays/winal
numdays = numdays-(winal_no*winal)
kin_no = numdays ! What is left is simply the days
long_carry = ' ' ! blank it out
write(long_carry,'(4(i2.2,"."),I2.2)') baktun_no,katun_no,tun_no,winal_no,kin_no
!
! OK. Now the longcount is done, let's calculate Tzolk´in, Haab´ & Nightlord (the calendar round)
!
haab_carry = " "
L = mod((keptdays+65),365)
mo = (L/20)+1
da = mod(l,20)
if(da.ne.0)then
write(haab_carry,'(i2,1x,a)') da,haab(mo)
else
write(haab_carry,'(a,1x,a)') 'Chum',haab(mo)
endif
!
! Ok, Now let's calculate the Tzolk´in
! The calendar starts on the 4 Ahu
tzolkin_carry = " " ! Total blank the carrier
mo = mod((keptdays+16),20) + 1
da = mod((keptdays+5),13) + 1
write(tzolkin_carry,'(i2,1x,a)') da,tzolkin(mo)
!
! Now let's have a look at the lords of the night
! There are 9 lords of the night, let's assume that they start on the first day of the year
!
numdays = keptdays -startdate ! Elapsed Julian days since start of calendar
J = mod(numdays,9) ! Number of days into this cycle
if (j.eq.0) j = 9
nightlord = night_lords(j)
RETURN
contains
!
FUNCTION JULDAY( Id , Mm, Iyyy)
IMPLICIT NONE
!
! PARAMETER definitions
!
INTEGER , PARAMETER :: IGREG = 15 + 31*(10 + 12*1582)
!
! Dummy arguments
!
INTEGER :: Id , Iyyy , Mm
INTEGER :: JULDAY
INTENT (IN) Id , Iyyy , Mm
!
! Local variables
!
INTEGER :: ja , jm , jy
!
jy = Iyyy
IF(jy == 0)STOP 'julday: there is no year zero'
IF(jy < 0)jy = jy + 1
IF(Mm > 2)THEN
jm = Mm + 1
ELSE
jy = jy - 1
jm = Mm + 13
END IF
JULDAY = 365*jy + INT(0.25D0*jy + 2000.D0) + INT(30.6001D0*jm) + Id + 1718995
IF(Id + 31*(Mm + 12*Iyyy) >= IGREG)THEN
ja = INT(0.01D0*jy)
JULDAY = JULDAY + 2 - ja + INT(0.25D0*ja)
END IF
RETURN
END FUNCTION JULDAY
END SUBROUTINE maya_time
- Output:
16-5-2071 1 Ok 18 Sip 13.02.19.04.10 (G9) Tlaloc 19-6-2004 4 Ben 16 Sotz´ 12.19.11.06.13 (G7) Tlazolteotl 18-12-2012 1 Kaban Chum K´ank´in 12.19.19.17.17 (G6) Chalchiuhtlicue 21-12-2012 4 Ajaw 3 K´ank´in 13.00.00.00.00 (G9) Tlaloc 19-1-2019 1 Ajaw 13 Muwan 13.00.06.03.00 (G6) Chalchiuhtlicue 27-3-2019 3 Manik´ Chum Wayeb´ 13.00.06.06.07 (G1) Xiuhtecuhtli 29-2-2020 4 Kimi 14 K´ayab 13.00.07.05.06 (G7) Tlazolteotl 1-3-2020 5 Manik´ 15 K´ayab 13.00.07.05.07 (G8) Tepeyollotl
FreeBASIC
#include "datetime.bi"
Type DateResult
As String long_date
As String round_date
End Type
Function IntToStr(num As Integer, ancho As Integer = 2) As String
Return Right("00" & Str(num), ancho)
End Function
Function JulianDate(y As Integer, m As Integer, d As Integer) As Long
Dim As Long a = (14 - m) \ 12
y += 4800 - a
m += 12 * a - 3
Return d + ((153 * m + 2) \ 5) + 365 * y + (y \ 4) - (y \ 100) + (y \ 400) - 32045
End Function
Function g2m(dateStr As String, gtm_correlation As Boolean = True) As DateResult
Dim As DateResult result
' Constants and arrays
Dim As Long correlation = Iif(gtm_correlation, 584283, 584285)
Dim As Long long_count_days(4) = {144000, 7200, 360, 20, 1}
Dim As String tzolkin_months(19) = { _
"Imix'", "Ik'", "Ak'bal", "K'an", "Chikchan", "Kimi", "Manik'", "Lamat", _
"Muluk", "Ok", "Chuwen", "Eb", "Ben", "Hix", "Men", "K'ib'", "Kaban", _
"Etz'nab'", "Kawak", "Ajaw" }
Dim As String haad_months(18) = { _
"Pop", "Wo'", "Sip", "Sotz'", "Sek", "Xul", "Yaxk'in", "Mol", "Ch'en", _
"Yax", "Sak'", "Keh", "Mak", "K'ank'in", "Muwan", "Pax", "K'ayab", _
"Kumk'u", "Wayeb'" }
' Parse date string (YYYY-MM-DD)
Dim As Integer y = Valint(Mid(dateStr, 1, 4))
Dim As Integer m = Valint(Mid(dateStr, 6, 2))
Dim As Integer d = Valint(Mid(dateStr, 9, 2))
' Calculate Julian days
Dim As Long julian_days = JulianDate(y, m, d)
' Calculate long count date
Dim As Long remainder = julian_days - correlation
Dim As Integer long_parts(4)
For i As Integer = 0 To 4
long_parts(i) = remainder \ long_count_days(i)
remainder Mod= long_count_days(i)
Next
' Format long date
result.long_date = ""
For i As Integer = 0 To 4
If i > 0 Then result.long_date &= "."
result.long_date &= IntToStr(long_parts(i))
Next
' Calculate round calendar date
Dim As Integer tzolkin_month = (julian_days + 16) Mod 20
Dim As Integer tzolkin_day = ((julian_days + 5) Mod 13) + 1
Dim As Integer haab_month = ((julian_days + 65) Mod 365) \ 20
Dim As String haab_day
Dim As Integer haab_day_num = ((julian_days + 65) Mod 365) Mod 20
haab_day = Iif(haab_day_num = 0, "Chum", Str(haab_day_num))
Dim As Integer lord_number = (julian_days - correlation) Mod 9
If lord_number = 0 Then lord_number = 9
' Format round date
result.round_date = Trim(Str(tzolkin_day)) & " " & _
Left(tzolkin_months(tzolkin_month) & Space(10), 10) & _
Right(Space(4) & Trim(haab_day), 4) & " " & _
Left(haad_months(haab_month) & Space(8), 8) & _
Space(7) & "G" & Trim(Str(lord_number))
Return result
End Function
' Main program
Print " Gregorian Long Tzolk'in Haab' Lord of"
Print " Date Count # Name Day Month the Night"
Print "---------- -------------- -------- ------------- ---------"
Dim As String dates(9) = { _
"1961-10-06", "1963-11-21", "2004-06-19", "2012-12-18", "2012-12-21", _
"2019-01-19", "2019-03-27", "2020-02-29", "2020-03-01", "2071-05-16" }
Dim As DateResult result
For i As Integer = 0 To 9
result = g2m(dates(i))
Print dates(i); " "; result.long_date; " "; result.round_date
Next
Sleep
- Output:
Gregorian Long Tzolk'in Haab' Lord of Date Count # Name Day Month the Night ---------- -------------- -------- ------------- --------- 1961-10-06 12.17.08.00.16 7 K'ib' 14 Ch'en G7 1963-11-21 12.17.10.03.12 3 Eb Chum Keh G9 2004-06-19 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 13.00.07.05.07 5 Manik' 15 K'ayab G8 2071-05-16 13.02.19.04.10 1 Ok 18 Sip G9
FutureBasic
//=================================================================
// Convert Gregorian to real Julian Date (not JDE)
// on entry Gregorian M = month, D = day, Y = YYYY
// on exit Long JD = Julian Date
//=================================================================
local fn Greg2Julian (M as Int, D as Int, Y as Int) as Long
Long JD
JD= D-32075+1461*(Y+4800+(M-14)/12)/4+367*(M-2-(M-14)/12*12)/12-3*((Y+4900+(M-14)/12)/100)/4
End fn = JD
//==================================================================
// Convert Gregorian to Mayan Calendar
// on entry Gregorian M = month, D = day, Y = YYYY
// On exit CFStringRef of Mayan calendar
//==================================================================
local fn Greg2Mayan (M as Int, D as Int, Y as Int) as CFStringRef
CFStringRef tM(19),hM(18) //Tzolkin and Haad Months
CFStringRef result
Long longParts(5)
Double remainder
Double JulianDays //Julian Date
Double LCD(4) //long count days
Double correlation //Day of creation GTM
correlation = 584283 //Julian date of Monday 3114 B.C. September 6, @noon
CFStringRef longDate, roundDate, HaabDay, tmp
Long tzolkinMonth, tzolkinDay
Long haabMonth, haabDayNum
Long lordNumber // Lord of the Nights, nine Deity, God 1 through God 9 (G1 - G9)
Int i
// Sacred Tzolk'in Months, 20 days
tM(0) = @"Imix'": tM(1) = @"Ik'": tM(2) = @"Ak'bal": tM(3) = @"K'an"
tM(4) = @"Chikchan": tM(5) = @"Kimi": tM(6) = @"Manik'": tM(7) = @"Lamat"
tM(8) = @"Muluk": tM(9) = @"Ok": tM(10) = @"Chuwen": tM(11) = @"Eb"
tM(12) = @"Ben": tM(13) = @"Hix": tM(14) = @"Men": tM(15) = @"K'ib'"
tM(16) = @"Kaban": tM(17) = @"Etz'nab'": tM(18) = @"Kawak": tM(19) = @"Ajaw"
// Civil Haab Months 20 days
hM(0) = @"Pop": hM(1) = @"Wo'": hM(2) = @"Sip": hM(3) = @"Sotz'"
hM(4) = @"Sek": hM(5) = @"Xul": hM(6) = @"Yaxk'in": hM(7) = @"Mol"
hM(8) = @"Ch'en": hM(9) = @"Yax": hM(10) = @"Sak'": hM(11) = @"Keh"
hM(12) = @"Mak": hM(13) = @"K'ank'in": hM(14) = @"Muwan": hM(15) = @"Pax"
hM(16) = @"K'ayab": hM(17) = @"Kumk'u": hM(18) = @"Wayeb'"
// Long count days
LCD(0) = 144000: LCD(1) = 7200: LCD(2) = 360: LCD(3) = 20: LCD(4) = 1
JulianDays = fn Greg2Julian (M, D, Y)
remainder = JulianDays - correlation
For i = 0 To 4
longParts(i) = Fix(remainder / LCD(i))
remainder = remainder - (longParts(i) * LCD(i))
Next i
longDate = @""
For i = 0 To 4
If i > 0 Then longDate = concat (longDate,@".")
tmp = mid(str(longParts(i)),1)
if len(tmp) < 2 then tmp = concat(@"0",tmp)
longDate = concat(longDate, tmp)
Next i
tzolkinMonth = fix((julianDays + 16) Mod 20)
tzolkinDay = fix(((julianDays + 5) Mod 13)) + 1
haabMonth = fix(((julianDays + 65) Mod 365) / 20)
haabDayNum = fix(((julianDays + 65) Mod 365) Mod 20)
If haabDayNum = 0
haabDay = @"Chum"
Else
haabDay = mid(Str(haabDayNum),1)
End If
lordNumber = Fix((julianDays - correlation) Mod 9)
If lordNumber = 0 Then lordNumber = 9
roundDate = @""
roundDate = concat(roundDate, @" ", mid(str(tzolkinDay),1), @"\t", tM(tzolkinMonth), @" ", haabDay, @" ", hM(haabMonth), @" G", mid(str(lordNumber),1))
result = concat(longDate, @" ", roundDate)
end fn = result
Window 1
CFStringRef mayanDate, GregDate
CFArrayRef comps
Int i,mm,dd,yy
CFStringRef testDate(7)
testDate(1) = @"2004-06-19": testDate(2) = @"2012-12-18": testDate(3) = @"2012-12-21": testDate(4) = @"2019-01-19"
testDate(5) = @"2019-03-27": testDate(6) = @"2020-02-29": testDate(7) = @"2020-03-01"
for i = 1 to 7
GregDate = testDate(i)
comps = fn StringComponentsSeparatedByString(GregDate, @"-" )
dd = IntVal(comps[2])
mm = IntVal(comps[1])
yy = IntVal(comps[0])
mayanDate = fn Greg2Mayan (mm,dd,yy)
print GregDate;" - ";mayanDate
next i
handleEvents
- Output:
2004-06-19 - 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 - 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 - 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 - 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 - 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 - 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 - 13.00.07.05.07 5 Manik' 15 K'ayab G8
Go
package main
import (
"fmt"
"strconv"
"strings"
"time"
)
var sacred = strings.Fields("Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw")
var civil = strings.Fields("Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh Mak K’ank’in Muwan’ Pax K’ayab Kumk’u Wayeb’")
var (
date1 = time.Date(2012, time.December, 21, 0, 0, 0, 0, time.UTC)
date2 = time.Date(2019, time.April, 2, 0, 0, 0, 0, time.UTC)
)
func tzolkin(date time.Time) (int, string) {
diff := int(date.Sub(date1).Hours()) / 24
rem := diff % 13
if rem < 0 {
rem = 13 + rem
}
var num int
if rem <= 9 {
num = rem + 4
} else {
num = rem - 9
}
rem = diff % 20
if rem <= 0 {
rem = 20 + rem
}
return num, sacred[rem-1]
}
func haab(date time.Time) (string, string) {
diff := int(date.Sub(date2).Hours()) / 24
rem := diff % 365
if rem < 0 {
rem = 365 + rem
}
month := civil[(rem+1)/20]
last := 20
if month == "Wayeb’" {
last = 5
}
d := rem%20 + 1
if d < last {
return strconv.Itoa(d), month
}
return "Chum", month
}
func longCount(date time.Time) string {
diff := int(date.Sub(date1).Hours()) / 24
diff += 13 * 400 * 360
baktun := diff / (400 * 360)
diff %= 400 * 360
katun := diff / (20 * 360)
diff %= 20 * 360
tun := diff / 360
diff %= 360
winal := diff / 20
kin := diff % 20
return fmt.Sprintf("%d.%d.%d.%d.%d", baktun, katun, tun, winal, kin)
}
func lord(date time.Time) string {
diff := int(date.Sub(date1).Hours()) / 24
rem := diff % 9
if rem <= 0 {
rem = 9 + rem
}
return fmt.Sprintf("G%d", rem)
}
func main() {
const shortForm = "2006-01-02"
dates := []string{
"2004-06-19",
"2012-12-18",
"2012-12-21",
"2019-01-19",
"2019-03-27",
"2020-02-29",
"2020-03-01",
"2071-05-16",
}
fmt.Println(" Gregorian Tzolk’in Haab’ Long Lord of")
fmt.Println(" Date # Name Day Month Count the Night")
fmt.Println("---------- -------- ------------- -------------- ---------")
for _, dt := range dates {
date, _ := time.Parse(shortForm, dt)
n, s := tzolkin(date)
d, m := haab(date)
lc := longCount(date)
l := lord(date)
fmt.Printf("%s %2d %-8s %4s %-9s %-14s %s\n", dt, n, s, d, m, lc, l)
}
}
- Output:
Gregorian Tzolk’in Haab’ Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- 2004-06-19 4 Ben 16 Sotz’ 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K’ank’in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K’ank’in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan’ 13.0.6.3.0 G6 2019-03-27 3 Manik’ Chum Wayeb’ 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K’ayab 13.0.7.5.6 G7 2020-03-01 5 Manik’ 15 K’ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
J
Implementation:
require 'types/datetime'
NB. 1794214= (0 20 18 20 20#.13 0 0 0 0)-todayno 2012 12 21
longcount=: {{ rplc&' .'":0 20 18 20 20#:y+1794214 }}
tsolkin=: (cut {{)n
Imix’ Ik’ Ak’bal K’an Chikchan
Kimi Manik’ Lamat Muluk Ok
Chuwen Eb Ben Hix Men
K’ib’ Kaban Etz’nab’ Kawak Ajaw
}}-.LF){{ (":1+13|y-4),' ',(20|y-7){::m }}
haab=:(cut {{)n
Pop Wo’ Sip Sotz’ Sek Xul
Yaxk’in Mol Ch’en Yax Sak’ Keh
Mak K’ank’in Muwan Pax K’ayab Kumk’u
Wayeb’
}}-.LF){{
'M D'=.0 20#:365|y-143
({{ if.*y do.":y else.'Chum'end. }} D),' ',(M-0=D){::m
}}
round=: [:;:inv tsolkin;haab;'G',&":1+9|]
gmt=: >@(fmtDate;round;longcount)@todayno
J's todayno counts days from January 1, 1800. And, each of these date formatting routines expects a number generated by todayno, with hard coded offsets, if necessary, to make this work. (The lord of night number uses an offset of zero, in this context.)
Also, in haab, our 'chum' days are zeros from modulo arithmetic (and, thus, belong to the previous month).
Task examples:
gmt 2004 6 19
June 19, 2004
4 Ben 16 Sotz’ G7
12.19.10.4.13
gmt 2012 12 18
December 18, 2012
1 Kaban Chum Mak G6
12.19.17.19.17
gmt 2012 12 21
December 21, 2012
4 Ajaw 3 K’ank’in G9
13.0.0.0.0
gmt 2019 1 19
January 19, 2019
1 Ajaw 13 Muwan G6
13.0.5.11.0
gmt 2019 3 27
March 27, 2019
3 Manik’ Chum Kumk’u G1
13.0.5.14.7
gmt 2019 2 29
March 1, 2019
3 Imix’ 14 K’ayab G2
13.0.5.13.1
gmt 2019 3 1
March 1, 2019
3 Imix’ 14 K’ayab G2
13.0.5.13.1
Java
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
public final class MayanCalendar {
public static void main(String[] aArgs) {
List<LocalDate> testDates = List.of( LocalDate.parse("2004-06-19"),
LocalDate.parse("2012-12-18"),
LocalDate.parse("2012-12-21"),
LocalDate.parse("2019-01-19"),
LocalDate.parse("2019-03-27"),
LocalDate.parse("2020-02-29"),
LocalDate.parse("2020-03-01"),
LocalDate.parse("2071-05-16"),
LocalDate.parse("2020-02-02") );
System.out.println("Gregorian Long Count Tzolk'in Haab' Lords of the Night");
System.out.println("------------------------------------------------------------------------------");
for ( LocalDate date : testDates ) {
System.out.println(String.format("%-15s%-19s%-12s%-18s%s",
date.toString(), longCount(date), tzolkin(date), haab(date), lordsOfTheNight(date)));
}
}
private static String lordsOfTheNight(LocalDate aGregorian) {
long daysBetween = ChronoUnit.DAYS.between(CREATION_TZOLKIN, aGregorian);
long remainder = Math.floorMod(daysBetween, 9);
return "G" + ( ( remainder <= 0 ) ? remainder + 9 : remainder );
}
private static String longCount(LocalDate aGregorian) {
long daysBetween = ChronoUnit.DAYS.between(CREATION_TZOLKIN, aGregorian) + 13 * 360 * 400;
long baktun = Math.floorDiv(daysBetween, 360 * 400);
daysBetween = Math.floorMod(daysBetween, 360 * 400);
long katun = Math.floorDiv(daysBetween, 20 * 360);
daysBetween = Math.floorMod(daysBetween, 20 * 360);
long tun = Math.floorDiv(daysBetween, 360);
daysBetween = Math.floorMod(daysBetween, 360);
long winal = Math.floorDiv(daysBetween, 20);
long kin = Math.floorMod(daysBetween, 20);
StringBuilder result = new StringBuilder();
for ( long number : List.of( baktun, katun, tun, winal, kin ) ) {
String value = String.valueOf(number) + ".";
result.append( number <= 9 ? "0" + value : value );
}
return result.toString().substring(0, result.length() - 1);
}
private static String haab(LocalDate aGregorian) {
long daysBetween = ChronoUnit.DAYS.between(ZERO_HAAB, aGregorian);
int remainder = Math.floorMod(daysBetween, 365);
String month = Haab.get(Math.floorDiv(remainder + 1, 20));
int dayOfMonth = Math.floorMod(remainder, 20) + 1;
return ( dayOfMonth < daysPerMayanMonth(month) ) ? dayOfMonth + " " + month : "Chum " + month;
}
private static String tzolkin(LocalDate aGregorian) {
long daysBetween = ChronoUnit.DAYS.between(CREATION_TZOLKIN, aGregorian);
int remainder = Math.floorMod(daysBetween, 13);
remainder += ( remainder <= 9 ) ? 4 : -9;
return remainder + " " + Tzolkin.get(Math.floorMod(daysBetween - 1, 20));
}
private static int daysPerMayanMonth(String aMonth) {
return ( aMonth == "Wayeb'" ) ? 5 : 20;
}
private static List<String> Tzolkin = List.of( "Imix'", "Ik'", "Ak'bal", "K'an", "Chikchan", "Kimi", "Manik'",
"Lamat", "Muluk", "Ok", "Chuwen", "Eb", "Ben", "Hix", "Men", "K'ib'", "Kaban", "Etz'nab'", "Kawak", "Ajaw" );
private static List<String> Haab = List.of( "Pop", "Wo'", "Sip", "Sotz'", "Sek", "Xul", "Yaxk'in", "Mol",
"Ch'en", "Yax", "Sak'", "Keh", "Mak", "K'ank'in", "Muwan", "Pax", "K'ayab", "Kumk'u", "Wayeb'" );
private static final LocalDate CREATION_TZOLKIN = LocalDate.parse("2012-12-21");
private static final LocalDate ZERO_HAAB = LocalDate.parse("2019-04-02");
}
- Output:
Gregorian Long Count Tzolk'in Haab' Lords of the Night ------------------------------------------------------------------------------ 2004-06-19 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 13.00.07.05.07 5 Manik' 15 K'ayab G8 2071-05-16 13.02.19.04.10 1 Ok 18 Sip G9 2020-02-02 13.00.07.03.19 3 Kawak 7 Pax G7
jq
Adapted from Wren
Works with jq, the C implementation of jq
Works with gojq, the Go implementation of jq
In this entry, the functions for converting Gregorian dates to dates in the Mayan calendar take the form of zero-arity filters that expect, as input, strings of the form "yyyy-mm-dd" or JSON Date objects of the form {"year", "month", "day"}.
### General utilities
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
def rpad($len): tostring | ($len - length) as $l | . + (" " * $l);
# days_between("2020-01-01"; "2020-01-02") #=> 1
# days_between("2020-01-02"; "2020-01-01") #=> -1
def days_between($yyyymmddBefore; $yyyymmddAfter):
(yyyymmddBefore | strptime("%Y-%m-%d") | mktime) as $before
| (yyyymmddAfter | strptime("%Y-%m-%d") | mktime) as $after
# leap seconds are always inserted
| (($after - $before) / (24*60*60) | floor) ;
### `Date` objects
def Date($year; $month; $day): {$year, $month, $day};
# Convert a Date object to a string yyyy-mm-dd
# Other inputs are (currently) unscathed.
def yyyymmdd:
if type == "object" then "\(.year)-\(.month)-\(.day)"
else .
end;
### Mayan Calendar
def sacred:
"Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw"
| split(" ");
def civil:
"Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh Mak K’ank’in Muwan’ Pax K’ayab Kumk’u Wayeb’"
| split(" ");
def CREATION_TZOLKIN: "2012-12-21";
# Input: Date or yyyy-mm-dd
def tzolkin:
(days_between(CREATION_TZOLKIN; yyyymmdd)) as $diff
| {rem: ($diff % 13)}
| if .rem < 0 then .rem += 13 end
| .num = (if .rem <= 9 then .rem + 4 else .rem - 9 end)
| .rem = $diff % 20
| if .rem <= 0 then .rem += 20 end
| [.num, sacred[.rem-1] ] ;
# Input: Date or yyyy-mm-dd
def haab:
def ZERO_HAAB: "2019-04-02";
(days_between(ZERO_HAAB; yyyymmdd)) as $diff
| {rem: ($diff % 365)}
| if .rem < 0 then .rem += 365 end
| .month = civil[((.rem+1)/20)|floor]
| .last = (if .month == "Wayeb'" then 5 else 20 end)
| .d = .rem%20 + 1
| if .d < .last then [(.d|tostring), .month]
else ["Chum", .month]
end;
# Input: Date or yyyy-mm-dd
def longCount:
{diff: days_between(CREATION_TZOLKIN; yyyymmdd)}
| .diff += 13*400*360
| .baktun = ((.diff/(400*360)) | floor)
| .diff = .diff % (400*360)
| .katun = ((.diff/(20 * 360))|floor)
| .diff = .diff % (20*360)
| .tun = ((.diff/360)|floor)
| .diff = .diff % 360
| .winal = ((.diff/20)|floor)
| .kin = .diff % 20
| [.baktun, .katun, .tun, .winal, .kin]
| join(".");
# Input: Date or yyyy-mm-dd
def lord:
{diff: days_between(CREATION_TZOLKIN; yyyymmdd)}
| .rem = .diff % 9
| if .rem <= 0 then .rem += 9 end
| "G\(.rem)";
def dates: [
"1961-10-06",
"1963-11-21",
"2004-06-19",
"2012-12-18",
"2012-12-21",
"2019-01-19",
"2019-03-27",
"2020-02-29",
"2020-03-01",
"2071-05-16"
];
" Gregorian Tzolk’in Haab’ Long Lord of",
" Date # Name Day Month Count the Night",
"---------- -------- ------------- -------------- ---------",
# Date.default = Date.isoDate
(dates[]
| tzolkin as [$n, $s]
| haab as [$d, $m]
| [., ($n | lpad(4)), ($s | rpad(8)), ($d|lpad(4)), ($m|rpad(8)), (longCount|lpad(20)), (lord|lpad(6))]
| join(" ")
)
- Output:
Gregorian Tzolk’in Haab’ Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- 1961-10-06 7 K’ib’ 14 Ch’en 12.17.8.0.16 G7 1963-11-21 3 Eb Chum Keh 12.17.10.3.12 G9 2004-06-19 4 Ben 16 Sotz’ 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K’ank’in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K’ank’in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan’ 13.0.6.3.0 G6 2019-03-27 3 Manik’ Chum Wayeb’ 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K’ayab 13.0.7.5.6 G7 2020-03-01 5 Manik’ 15 K’ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
Julia
using Dates
const Tzolk´in = [
"Imix´", "Ik´", "Ak´bal", "K´an", "Chikchan", "Kimi", "Manik´", "Lamat", "Muluk", "Ok",
"Chuwen", "Eb", "Ben", "Hix", "Men", "K´ib´", "Kaban", "Etz´nab´", "Kawak", "Ajaw"
]
const Haab´ = [
"Pop", "Wo´", "Sip", "Sotz´", "Sek", "Xul", "Yaxk´in", "Mol", "Ch´en", "Yax",
"Sak´", "Keh", "Mak", "K´ank´in", "Muwan", "Pax", "K´ayab", "Kumk´u", "Wayeb´"
]
const creationTzolk´in = Date(2012, 12, 21)
const zeroHaab´ = Date(2019, 4, 2)
daysperMayanmonth(month) = (month == "Wayeb´" ? 5 : 20)
function tzolkin(gregorian::Date)
deltadays = (gregorian - creationTzolk´in).value
rem = mod1(deltadays, 13)
return string(rem <= 9 ? rem + 4 : rem - 9) * " " * Tzolk´in[mod1(deltadays, 20)]
end
function haab(gregorian::Date)
rem = mod1((gregorian - zeroHaab´).value, 365)
month = Haab´[(rem + 21) ÷ 20]
dayofmonth = rem % 20 + 1
return dayofmonth < daysperMayanmonth(month) ? "$dayofmonth $month" : "Chum $month"
end
function tolongdate(gregorian::Date)
delta = (gregorian - creationTzolk´in).value + 13 * 360 * 400
baktun = delta ÷ (360 * 400)
delta %= (400 * 360)
katun = delta ÷ (20 * 360)
delta %= (20 * 360)
tun = delta ÷ 360
delta %= 360
winal, kin = divrem(delta, 20)
return mapreduce(x -> lpad(x, 3), *, [baktun, katun, tun, winal, kin])
end
nightlord(gregorian::Date) = "G$(mod1((gregorian - creationTzolk´in).value, 9))"
testdates = [
Date(1963, 11, 21), Date(2004, 06, 19), Date(2012, 12, 18), Date(2012, 12, 21),
Date(2019, 01, 19), Date(2019, 03, 27), Date(2020, 02, 29), Date(2020, 03, 01),
Date(2071, 5, 16), Date(2020, 2, 2)
]
println("Gregorian Long Count Tzolk´in Haab´ Nightlord")
println("-----------------------------------------------------------------")
for date in testdates
println(rpad(date,14), rpad(tolongdate(date), 18), rpad(tzolkin(date), 10),
rpad(haab(date), 15), nightlord(date))
end
- Output:
Gregorian Long Count Tzolk´in Haab´ Nightlord ----------------------------------------------------------------- 1963-11-21 12 17 10 3 12 3 Eb Chum Keh G9 2004-06-19 12 19 11 6 13 4 Ben 16 Sotz´ G7 2012-12-18 12 19 19 17 17 1 Kaban Chum K´ank´in G6 2012-12-21 13 0 0 0 0 4 Ajaw 3 K´ank´in G9 2019-01-19 13 0 6 3 0 1 Ajaw 13 Muwan G6 2019-03-27 13 0 6 6 7 3 Manik´ Chum Wayeb´ G1 2020-02-29 13 0 7 5 6 4 Kimi 14 K´ayab G7 2020-03-01 13 0 7 5 7 5 Manik´ 15 K´ayab G8 2071-05-16 13 2 19 4 10 1 Ok 18 Sip G9 2020-02-02 13 0 7 3 19 3 Kawak 7 Pax G7
Mathematica /Wolfram Language
sacred = {"Imix\[CloseCurlyQuote]", "Ik\[CloseCurlyQuote]",
"Ak\[CloseCurlyQuote]bal", "K\[CloseCurlyQuote]an", "Chikchan",
"Kimi", "Manik\[CloseCurlyQuote]", "Lamat", "Muluk", "Ok",
"Chuwen", "Eb", "Ben", "Hix", "Men",
"K\[CloseCurlyQuote]ib\[CloseCurlyQuote]", "Kaban",
"Etz\[CloseCurlyQuote]nab\[CloseCurlyQuote]", "Kawak", "Ajaw"};
civil = {"Pop", "Wo\[CloseCurlyQuote]", "Sip",
"Sotz\[CloseCurlyQuote]", "Sek", "Xul", "Yaxk\[CloseCurlyQuote]in",
"Mol", "Ch\[CloseCurlyQuote]en", "Yax", "Sak\[CloseCurlyQuote]",
"Keh", "Mak", "K\[CloseCurlyQuote]ank\[CloseCurlyQuote]in",
"Muwan\[CloseCurlyQuote]", "Pax", "K\[CloseCurlyQuote]ayab",
"Kumk\[CloseCurlyQuote]u", "Wayeb\[CloseCurlyQuote]"};
date1 = {2012, 12, 21, 0, 0, 0};
date2 = {2019, 4, 2, 0, 0, 0};
ClearAll[Tzolkin]
Tzolkin[date_] := Module[{diff, rem, num},
diff = QuantityMagnitude[DateDifference[date1, date], "Days"];
rem = Mod[diff, 13];
If[rem <= 9,
num = rem + 4
,
num = rem - 9
];
rem = Mod[diff, 20, 1];
ToString[num] <> " " <> sacred[[rem]]
]
ClearAll[Haab]
Haab[date_] := Module[{diff, rem, month, last, d},
diff = QuantityMagnitude[DateDifference[date2, date], "Days"];
rem = Mod[diff, 365];
month = civil[[Floor[(rem + 1)/20] + 1]];
last = 20;
If[month == Last[civil],
last = 5
];
d = Mod[rem, 20] + 1;
If[d < last,
ToString[d] <> " " <> month
,
"Chum " <> month
]
]
ClearAll[LongCount]
LongCount[date_] := Module[{diff, baktun, katun, tun, winal, kin},
diff = QuantityMagnitude[DateDifference[date1, date], "Days"];
diff += 13 400 360;
{baktun, diff} = QuotientRemainder[diff, 400 360];
{katun, diff} = QuotientRemainder[diff, 20 360];
{tun, diff} = QuotientRemainder[diff, 360];
{winal, kin} = QuotientRemainder[diff, 20];
StringRiffle[ToString /@ {baktun, katun, tun, winal, kin}, "."]
]
ClearAll[LordOfTheNight]
LordOfTheNight[date_] := Module[{diff, rem},
diff = QuantityMagnitude[DateDifference[date1, date], "Days"];
rem = Mod[diff, 9, 1];
"G" <> ToString[rem]
]
data = {{2004, 06, 19}, {2012, 12, 18}, {2012, 12, 21}, {2019, 01,
19}, {2019, 03, 27}, {2020, 02, 29}, {2020, 03, 01}, {2071, 05,
16}};
tzolkindata = Tzolkin /@ data;
haabdata = Haab /@ data;
longcountdata = LongCount /@ data;
lotndata = LordOfTheNight /@ data;
{DateObject /@ data, tzolkindata, haabdata, longcountdata, lotndata} // Transpose // Grid
- Output:
Sat 19 Jun 2004 4 Ben 16 Sotz' 12.19.11.6.13 G7 Tue 18 Dec 2012 1 Kaban Chum K'ank'in 12.19.19.17.17 G6 Fri 21 Dec 2012 4 Ajaw 3 K'ank'in 13.0.0.0.0 G9 Sat 19 Jan 2019 1 Ajaw 13 Muwan' 13.0.6.3.0 G6 Wed 27 Mar 2019 3 Manik' Chum Wayeb' 13.0.6.6.7 G1 Sat 29 Feb 2020 4 Kimi 14 K'ayab 13.0.7.5.6 G7 Sun 1 Mar 2020 5 Manik' 15 K'ayab 13.0.7.5.7 G8 Sat 16 May 2071 1 Ok 18 Sip 13.2.19.4.10 G9
Nim
import math, strformat, times
const
Tzolk´in = ["Imix´", "Ik´", "Ak´bal", "K´an", "Chikchan", "Kimi", "Manik´", "Lamat", "Muluk", "Ok",
"Chuwen", "Eb", "Ben", "Hix", "Men", "K´ib´", "Kaban", "Etz´nab´", "Kawak", "Ajaw"]
Haab´ = ["Pop", "Wo´", "Sip", "Sotz´", "Sek", "Xul", "Yaxk´in", "Mol", "Ch´en", "Yax",
"Sak´", "Keh", "Mak", "K´ank´in", "Muwan", "Pax", "K´ayab", "Kumk´u", "Wayeb´"]
let
creationTzolk´in = initDateTime(21, mDec, 2012, 0, 0, 0, utc())
zeroHaab´ = initDateTime(2, mApr, 2019, 0, 0, 0, utc())
func daysPerMayanMonth(month: string): int =
if month == "Wayeb´": 5 else: 20
proc tzolkin(gregorian: DateTime): string =
let deltaDays = (gregorian - creationTzolk´in).inDays
let rem = floorMod(deltaDays, 13)
result = $(if rem <= 9: rem + 4 else: rem - 9) & ' ' & Tzolk´in[floorMod(deltaDays - 1, 20)]
proc haab(gregorian: DateTime): string =
let rem = floorMod((gregorian - zeroHaab´).inDays, 365)
let month = Haab´[(rem + 1) div 20]
let dayOfMonth = rem mod 20 + 1
result = if dayOfMonth < daysPerMayanMonth(month): &"{dayOfMonth} {month}" else: &"Chum {month}"
proc toLongDate(gregorian: DateTime): string =
var delta = (gregorian - creationTzolk´in).inDays + 13 * 360 * 400
var baktun = delta div (360 * 400)
delta = delta mod (400 * 360)
let katun = delta div (20 * 360)
delta = delta mod (20 * 360)
let tun = delta div 360
delta = delta mod 360
let winal = delta div 20
let kin = delta mod 20
result = &"{baktun:2} {katun:2} {tun:2} {winal:2} {kin:2}"
proc nightLord(gregorian: DateTime): string =
var rem = (gregorian - creationTzolk´in).inDays mod 9
if rem <= 0: rem += 9
result = 'G' & $rem
when isMainModule:
let testDates = [initDateTime(21, mNov, 1963, 0, 0, 0, utc()),
initDateTime(19, mJun, 2004, 0, 0, 0, utc()),
initDateTime(18, mDec, 2012, 0, 0, 0, utc()),
initDateTime(21, mDec, 2012, 0, 0, 0, utc()),
initDateTime(19, mJan, 2019, 0, 0, 0, utc()),
initDateTime(27, mMar, 2019, 0, 0, 0, utc()),
initDateTime(29, mFeb, 2020, 0, 0, 0, utc()),
initDateTime(01, mMar, 2020, 0, 0, 0, utc()),
initDateTime(16, mMay, 2071, 0, 0, 0, utc()),
initDateTime(02, mfeb, 2020, 0, 0, 0, utc())]
echo "Gregorian Long Count Tzolk´in Haab´ Nightlord"
echo "———————————————————————————————————————————————————————————————"
for date in testDates:
let dateStr = date.format("YYYY-MM-dd")
echo &"{dateStr:14} {date.toLongDate:16} {tzolkin(date):9} {haab(date):14} {nightLord(date)}"
- Output:
Gregorian Long Count Tzolk´in Haab´ Nightlord ——————————————————————————————————————————————————————————————— 1963-11-21 12 17 10 3 12 3 Eb Chum Keh G9 2004-06-19 12 19 11 6 13 4 Ben 16 Sotz´ G7 2012-12-18 12 19 19 17 17 1 Kaban Chum K´ank´in G6 2012-12-21 13 0 0 0 0 4 Ajaw 3 K´ank´in G9 2019-01-19 13 0 6 3 0 1 Ajaw 13 Muwan G6 2019-03-27 13 0 6 6 7 3 Manik´ Chum Wayeb´ G1 2020-02-29 13 0 7 5 6 4 Kimi 14 K´ayab G7 2020-03-01 13 0 7 5 7 5 Manik´ 15 K´ayab G8 2071-05-16 13 2 19 4 10 1 Ok 18 Sip G9 2020-02-02 13 0 7 3 19 3 Kawak 7 Pax G7
Perl
The module Math::BaseArith
provides mixed-radix conversion via the encode
routine (named as in APL).
use strict;
use warnings;
use utf8;
binmode STDOUT, ":utf8";
use Math::BaseArith;
use Date::Calc 'Delta_Days';
my @sacred = qw<Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok
Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw>;
my @civil = qw<Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh
Mak K’ank’in Muwan’ Pax K’ayab Kumk’u Wayeb’>;
my %correlation = (
'gregorian' => '2012-12-21',
'round' => [3,19,263,8],
'long' => 1872000,
);
sub mayan_calendar_round {
my $date = shift;
tzolkin($date), haab($date);
}
sub offset {
my $date = shift;
Delta_Days( split('-', $correlation{'gregorian'}), split('-', $date) );
}
sub haab {
my $date = shift;
my $index = ($correlation{'round'}[2] + offset $date) % 365;
my ($day, $month);
if ($index > 360) {
$day = $index - 360;
$month = $civil[18];
if ($day == 5) {
$day = 'Chum';
$month = $civil[0];
}
} else {
$day = $index % 20;
$month = $civil[int $index / 20];
if ($day == 0) {
$day = 'Chum';
$month = $civil[int (1 + $index) / 20];
}
}
$day, $month
}
sub tzolkin {
my $date = shift;
my $offset = offset $date;
1 + ($offset + $correlation{'round'}[0]) % 13,
$sacred[($offset + $correlation{'round'}[1]) % 20]
}
sub lord {
my $date = shift;
1 + ($correlation{'round'}[3] + offset $date) % 9
}
sub mayan_long_count {
my $date = shift;
my $days = $correlation{'long'} + offset $date;
encode($days, [20,20,20,18,20]);
}
print <<'EOH';
Gregorian Tzolk’in Haab’ Long Lord of
Date # Name Day Month Count the Night
-----------------------------------------------------------------------
EOH
for my $date (<1961-10-06 2004-06-19 2012-12-18 2012-12-21 2019-01-19 2019-03-27 2020-02-29 2020-03-01 2071-05-16>) {
printf "%10s %2s %-9s %4s %-10s %-14s G%d\n",
$date, mayan_calendar_round($date), join('.',mayan_long_count($date)), lord($date);
}
- Output:
Gregorian Tzolk’in Haab’ Long Lord of Date # Name Day Month Count the Night ----------------------------------------------------------------------- 1961-10-06 7 K’ib’ 14 Ch’en 12.17.8.0.16 G7 2004-06-19 4 Ben 16 Sotz’ 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K’ank’in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K’ank’in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan’ 13.0.6.3.0 G6 2019-03-27 3 Manik’ Chum Wayeb’ 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K’ayab 13.0.7.5.6 G7 2020-03-01 5 Manik’ 15 K’ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
Phix
with javascript_semantics include timedate.e sequence sacred = split("Imix' Ik' Ak'bal K'an Chikchan Kimi Manik' Lamat Muluk Ok Chuwen Eb Ben Hix Men K'ib' Kaban Etz'nab' Kawak Ajaw"), civil = split("Pop Wo' Sip Sotz' Sek Xul Yaxk'in Mol Ch'en Yax Sak' Keh Mak K'ank'in Muwan' Pax K'ayab Kumk'u Wayeb'"), date1 = parse_date_string("21/12/2012",{"DD/MM/YYYY"}), date2 = parse_date_string("2/4/2019",{"DD/MM/YYYY"}) function tzolkin(integer diff) integer rem = mod(diff,13) if rem<0 then rem += 13 end if integer num = iff(rem<=9?rem+4:rem-9) rem = mod(diff,20) if rem<=0 then rem += 20 end if return {num, sacred[rem]} end function function haab(integer diff) integer rem = mod(diff,365) if rem<0 then rem += 365 end if string month = civil[floor((rem+1)/20)+1] integer last = iff(month="Wayeb'"?5:20), d = mod(rem,20) + 1 return {iff(d<last?sprintf("%d",d):"Chum"), month} end function function longCount(integer diff) diff += 13 * 400 * 360 integer baktun := floor(diff/(400*360)) diff = mod(diff,400*360) integer katun := floor(diff/(20*360)) diff = mod(diff,20*360) integer tun = floor(diff/360) diff = mod(diff,360) integer winal = floor(diff/20), kin = mod(diff,20) return sprintf("%d.%d.%d.%d.%d", {baktun, katun, tun, winal, kin}) end function function lord(integer diff) integer rem = mod(diff,9) if rem<=0 then rem += 9 end if return sprintf("G%d", rem) end function constant dates = {"1961-10-06", "1963-11-21", "2004-06-19", "2012-12-18", "2012-12-21", "2019-01-19", "2019-03-27", "2020-02-29", "2020-03-01", "2071-05-16", }, headers = """ Gregorian Tzolk'in Haab' Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- """ procedure main() printf(1,headers) for i=1 to length(dates) do string dt = dates[i] timedate td = parse_date_string(dt,{"YYYY-MM-DD"}) integer diff1 = floor(timedate_diff(date1,td,DT_DAY) / (24*60*60)), diff2 = floor(timedate_diff(date2,td,DT_DAY) / (24*60*60)) {integer n, string s} = tzolkin(diff1) string {d, m} = haab(diff2), lc := longCount(diff1), l := lord(diff1) printf(1,"%s %2d %-8s %4s %-9s %-14s %s\n", {dt, n, s, d, m, lc, l}) end for end procedure main()
- Output:
Gregorian Tzolk'in Haab' Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- 1961-10-06 7 K'ib' 14 Ch'en 12.17.8.0.16 G7 1963-11-21 3 Eb Chum Keh 12.17.10.3.12 G9 2004-06-19 4 Ben 16 Sotz' 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K'ank'in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K'ank'in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan' 13.0.6.3.0 G6 2019-03-27 3 Manik' Chum Wayeb' 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K'ayab 13.0.7.5.6 G7 2020-03-01 5 Manik' 15 K'ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
Python
import datetime
def g2m(date, gtm_correlation=True):
"""
Translates Gregorian date into Mayan date, see
https://rosettacode.org/wiki/Mayan_calendar
Input arguments:
date: string date in ISO-8601 format: YYYY-MM-DD
gtm_correlation: GTM correlation to apply if True, Astronomical correlation otherwise (optional, True by default)
Output arguments:
long_date: Mayan date in Long Count system as string
round_date: Mayan date in Calendar Round system as string
"""
# define some parameters and names
correlation = 584283 if gtm_correlation else 584285
long_count_days = [144000, 7200, 360, 20, 1]
tzolkin_months = ['Imix’', 'Ik’', 'Ak’bal', 'K’an', 'Chikchan', 'Kimi', 'Manik’', 'Lamat', 'Muluk', 'Ok', 'Chuwen',
'Eb', 'Ben', 'Hix', 'Men', 'K’ib’', 'Kaban', 'Etz’nab’', 'Kawak', 'Ajaw'] # tzolk'in
haad_months = ['Pop', 'Wo’', 'Sip', 'Sotz’', 'Sek', 'Xul', 'Yaxk’in', 'Mol', 'Ch’en', 'Yax', 'Sak’', 'Keh', 'Mak',
'K’ank’in', 'Muwan', 'Pax', 'K’ayab', 'Kumk’u', 'Wayeb’'] # haab'
gregorian_days = datetime.datetime.strptime(date, '%Y-%m-%d').toordinal()
julian_days = gregorian_days + 1721425
# 1. calculate long count date
long_date = list()
remainder = julian_days - correlation
for days in long_count_days:
result, remainder = divmod(remainder, days)
long_date.append(int(result))
long_date = '.'.join(['{:02d}'.format(d) for d in long_date])
# 2. calculate round calendar date
tzolkin_month = (julian_days + 16) % 20
tzolkin_day = ((julian_days + 5) % 13) + 1
haab_month = int(((julian_days + 65) % 365) / 20)
haab_day = ((julian_days + 65) % 365) % 20
haab_day = haab_day if haab_day else 'Chum'
lord_number = (julian_days - correlation) % 9
lord_number = lord_number if lord_number else 9
round_date = f'{tzolkin_day} {tzolkin_months[tzolkin_month]} {haab_day} {haad_months[haab_month]} G{lord_number}'
return long_date, round_date
if __name__ == '__main__':
dates = ['2004-06-19', '2012-12-18', '2012-12-21', '2019-01-19', '2019-03-27', '2020-02-29', '2020-03-01']
for date in dates:
long, round = g2m(date)
print(date, long, round)
- Output:
2004-06-19 12.19.11.06.13 4 Ben 16 Sotz’ G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K’ank’in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K’ank’in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik’ Chum Wayeb’ G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K’ayab G7 2020-03-01 13.00.07.05.07 5 Manik’ 15 K’ayab G8
QBasic
The QB64 solution works without any changes.
QB64
DECLARE FUNCTION IntToStr$ (num AS LONG, ancho AS INTEGER)
DECLARE FUNCTION JulianDate# (y AS LONG, m AS LONG, d AS LONG)
DECLARE FUNCTION g2m$ (dateStr AS STRING)
Dim dates(6) As String
dates(0) = "2004-06-19": dates(1) = "2012-12-18": dates(2) = "2012-12-21"
dates(3) = "2019-01-19": dates(4) = "2019-03-27": dates(5) = "2020-02-29"
dates(6) = "2020-03-01"
Dim i As Integer
For i = 0 To 6
Print dates(i); " "; g2m$(dates(i))
Next i
'sleep
End
Function IntToStr$ (num As Long, ancho As Integer)
IntToStr$ = Right$("00" + LTrim$(Str$(num)), ancho)
End Function
Function JulianDate# (y As Long, m As Long, d As Long)
Dim a As Long
a = (14 - m) \ 12
y = y + 4800 - a
m = m + 12 * a - 3
JulianDate# = d + ((153 * m + 2) \ 5) + 365 * y + (y \ 4) - (y \ 100) + (y \ 400) - 32045
End Function
Function g2m$ (dateStr As String)
Dim longDate As String
Dim roundDate As String
Dim correlation As Double
correlation = 584283 'GTM correlation
Dim longCountDays(4) As Double
longCountDays(0) = 144000: longCountDays(1) = 7200
longCountDays(2) = 360: longCountDays(3) = 20: longCountDays(4) = 1
Dim tzolkinMonths(19) As String
tzolkinMonths(0) = "Imix'": tzolkinMonths(1) = "Ik'"
tzolkinMonths(2) = "Ak'bal": tzolkinMonths(3) = "K'an"
tzolkinMonths(4) = "Chikchan": tzolkinMonths(5) = "Kimi"
tzolkinMonths(6) = "Manik'": tzolkinMonths(7) = "Lamat"
tzolkinMonths(8) = "Muluk": tzolkinMonths(9) = "Ok"
tzolkinMonths(10) = "Chuwen": tzolkinMonths(11) = "Eb"
tzolkinMonths(12) = "Ben": tzolkinMonths(13) = "Hix"
tzolkinMonths(14) = "Men": tzolkinMonths(15) = "K'ib'"
tzolkinMonths(16) = "Kaban": tzolkinMonths(17) = "Etz'nab'"
tzolkinMonths(18) = "Kawak": tzolkinMonths(19) = "Ajaw"
Dim haadMonths(18) As String
haadMonths(0) = "Pop": haadMonths(1) = "Wo'"
haadMonths(2) = "Sip": haadMonths(3) = "Sotz'"
haadMonths(4) = "Sek": haadMonths(5) = "Xul"
haadMonths(6) = "Yaxk'in": haadMonths(7) = "Mol"
haadMonths(8) = "Ch'en": haadMonths(9) = "Yax"
haadMonths(10) = "Sak'": haadMonths(11) = "Keh"
haadMonths(12) = "Mak": haadMonths(13) = "K'ank'in"
haadMonths(14) = "Muwan": haadMonths(15) = "Pax"
haadMonths(16) = "K'ayab": haadMonths(17) = "Kumk'u"
haadMonths(18) = "Wayeb'"
Dim y As Long, m As Long, d As Long
y = Val(Mid$(dateStr, 1, 4))
m = Val(Mid$(dateStr, 6, 2))
d = Val(Mid$(dateStr, 9, 2))
Dim julianDays As Double
julianDays = JulianDate#(y, m, d)
Dim remainder As Double
remainder = julianDays - correlation
Dim longParts(4) As Long
For i = 0 To 4
longParts(i) = Int(remainder / longCountDays(i))
remainder = remainder - (longParts(i) * longCountDays(i))
Next i
longDate = ""
For i = 0 To 4
If i > 0 Then longDate = longDate + "."
longDate = longDate + IntToStr$(longParts(i), 2)
Next i
Dim tzolkinMonth As Long, tzolkinDay As Long
Dim haabMonth As Long, haabDayNum As Long
Dim lordNumber As Long
tzolkinMonth = Int((julianDays + 16) Mod 20)
tzolkinDay = Int(((julianDays + 5) Mod 13)) + 1
haabMonth = Int(((julianDays + 65) Mod 365) / 20)
haabDayNum = Int(((julianDays + 65) Mod 365) Mod 20)
Dim haabDay As String
If haabDayNum = 0 Then
haabDay = "Chum"
Else
haabDay = LTrim$(Str$(haabDayNum))
End If
lordNumber = Int((julianDays - correlation) Mod 9)
If lordNumber = 0 Then lordNumber = 9
roundDate = LTRIM$(STR$(tzolkinDay)) + " " + _
tzolkinMonths(tzolkinMonth) + " " + _
haabDay + " " + _
haadMonths(haabMonth) + " G" + _
LTRIM$(STR$(lordNumber))
g2m$ = longDate + " " + roundDate
End Function
- Output:
2004-06-19 12.19.11.06.13 4 Ben 16 Sotz' G7 2012-12-18 12.19.19.17.17 1 Kaban Chum K'ank'in G6 2012-12-21 13.00.00.00.00 4 Ajaw 3 K'ank'in G9 2019-01-19 13.00.06.03.00 1 Ajaw 13 Muwan G6 2019-03-27 13.00.06.06.07 3 Manik' Chum Wayeb' G1 2020-02-29 13.00.07.05.06 4 Kimi 14 K'ayab G7 2020-03-01 13.00.07.05.07 5 Manik' 15 K'ayab G8
Raku
(formerly Perl 6)
my @sacred = <Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok
Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw>;
my @civil = <Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh
Mak K’ank’in Muwan’ Pax K’ayab Kumk’u Wayeb’>;
my %correlation = :GMT({
:gregorian(Date.new('2012-12-21')),
:round([3,19,263,8]),
:long(1872000)
});
sub mayan-calendar-round ($date) { .&tzolkin, .&haab given $date }
sub offset ($date, $factor = 'GMT') { Date.new($date) - %correlation{$factor}<gregorian> }
sub haab ($date, $factor = 'GMT') {
my $index = (%correlation{$factor}<round>[2] + offset $date) % 365;
my ($day, $month);
if $index > 360 {
$day = $index - 360;
$month = @civil[18];
if $day == 5 {
$day = 'Chum';
$month = @civil[0];
}
} else {
$day = $index % 20;
$month = @civil[$index div 20];
if $day == 0 {
$day = 'Chum';
$month = @civil[(1 + $index) div 20];
}
}
$day, $month
}
sub tzolkin ($date, $factor = 'GMT') {
my $offset = offset $date;
1 + ($offset + %correlation{$factor}<round>[0]) % 13,
@sacred[($offset + %correlation{$factor}<round>[1]) % 20]
}
sub lord ($date, $factor = 'GMT') {
'G' ~ 1 + (%correlation{$factor}<round>[3] + offset $date) % 9
}
sub mayan-long-count ($date, $factor = 'GMT') {
my $days = %correlation{$factor}<long> + offset $date;
reverse $days.polymod(20,18,20,20);
}
# HEADER
say ' Gregorian Tzolk’in Haab’ Long Lord of ';
say ' Date # Name Day Month Count the Night';
say '-----------------------------------------------------------------------';
# DATES
<
1963-11-21
2004-06-19
2012-12-18
2012-12-21
2019-01-19
2019-03-27
2020-02-29
2020-03-01
2071-05-16
>.map: -> $date {
printf "%10s %2s %-9s %4s %-10s %-14s %6s\n", Date.new($date),
flat mayan-calendar-round($date), mayan-long-count($date).join('.'), lord($date);
}
- Output:
Gregorian Tzolk’in Haab’ Long Lord of Date # Name Day Month Count the Night ----------------------------------------------------------------------- 1963-11-21 3 Eb Chum Keh 12.17.10.3.12 G9 2004-06-19 4 Ben 16 Sotz’ 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K’ank’in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K’ank’in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan’ 13.0.6.3.0 G6 2019-03-27 3 Manik’ Chum Wayeb’ 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K’ayab 13.0.7.5.6 G7 2020-03-01 5 Manik’ 15 K’ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
Wren
import "./date" for Date
import "./fmt" for Fmt
var sacred = "Imix’ Ik’ Ak’bal K’an Chikchan Kimi Manik’ Lamat Muluk Ok Chuwen Eb Ben Hix Men K’ib’ Kaban Etz’nab’ Kawak Ajaw".split(" ")
var civil = "Pop Wo’ Sip Sotz’ Sek Xul Yaxk’in Mol Ch’en Yax Sak’ Keh Mak K’ank’in Muwan’ Pax K’ayab Kumk’u Wayeb’".split(" ")
var date1 = Date.new(2012, 12, 21)
var date2 = Date.new(2019, 4, 2)
var tzolkin = Fn.new { |date|
var diff = (date - date1).days
var rem = diff % 13
if (rem < 0) rem = 13 + rem
var num = (rem <= 9) ? rem + 4 : rem - 9
rem = diff % 20
if (rem <= 0) rem = 20 + rem
return [num, sacred[rem-1]]
}
var haab = Fn.new { |date|
var diff = (date - date2).days
var rem = diff % 365
if (rem < 0) rem = 365 + rem
var month = civil[((rem+1)/20).floor]
var last = (month == "Wayeb'") ? 5 : 20
var d = rem%20 + 1
if (d < last) return [d.toString, month]
return ["Chum", month]
}
var longCount = Fn.new { |date|
var diff = (date - date1).days
diff = diff + 13*400*360
var baktun = (diff/(400*360)).floor
diff = diff % (400*360)
var katun = (diff/(20 * 360)).floor
diff = diff % (20*360)
var tun = (diff/360).floor
diff = diff % 360
var winal = (diff/20).floor
var kin = diff % 20
return Fmt.swrite("$d.$d.$d.$d.$d", baktun, katun, tun, winal, kin)
}
var lord = Fn.new { |date|
var diff = (date - date1).days
var rem = diff % 9
if (rem <= 0) rem = 9 + rem
return Fmt.swrite("G$d", rem)
}
var dates = [
"1961-10-06",
"1963-11-21",
"2004-06-19",
"2012-12-18",
"2012-12-21",
"2019-01-19",
"2019-03-27",
"2020-02-29",
"2020-03-01",
"2071-05-16"
]
System.print(" Gregorian Tzolk’in Haab’ Long Lord of")
System.print(" Date # Name Day Month Count the Night")
System.print("---------- -------- ------------- -------------- ---------")
Date.default = Date.isoDate
for (dt in dates) {
var date = Date.parse(dt)
var ns = tzolkin.call(date)
var n = ns[0]
var s = ns[1]
var dm = haab.call(date)
var d = dm[0]
var m = dm[1]
var lc = longCount.call(date)
var l = lord.call(date)
Fmt.lprint("$s $2d $-8s $4s $-9s $-14s $s", [dt, n, s, d, m, lc, l])
}
- Output:
Gregorian Tzolk’in Haab’ Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- 1961-10-06 7 K’ib’ 14 Ch’en 12.17.8.0.16 G7 1963-11-21 3 Eb Chum Keh 12.17.10.3.12 G9 2004-06-19 4 Ben 16 Sotz’ 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K’ank’in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K’ank’in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan’ 13.0.6.3.0 G6 2019-03-27 3 Manik’ Chum Wayeb’ 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K’ayab 13.0.7.5.6 G7 2020-03-01 5 Manik’ 15 K’ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9
zkl
var [const]
sacred=T("Imix'","Ik'","Ak'bal","K'an","Chikchan","Kimi","Manik'","Lamat","Muluk","Ok",
"Chuwen","Eb","Ben","Hix","Men","K'ib'","Kaban","Etz'nab'","Kawak","Ajaw"),
civil=T("Pop","Wo'","Sip","Sotz'","Sek","Xul","Yaxk'in","Mol","Ch'en","Yax","Sak'","Keh",
"Mak","K'ank'in","Muwan'","Pax","K'ayab","Kumk'u","Wayeb'"),
Date=Time.Date,
// correlation dates:
Creation=T(2012, Date.December, 21), // 13.0.0.0.0, Mayan day of creation
OnePop=T(2019, Date.April, 2), // 1 Pop in 2019
;
fcn haab(date){ // (y,m,d)-->("Chum"|Int,month name)
diff:=Date.deltaDays(OnePop,date.xplode()); //--> signed int
rem:=diff%365;
if(rem<0) rem=365 + rem;
month,last := civil[(rem+1)/20], 20;
if(month==civil[-1]) last=5;
d:=rem%20 + 1;
if(d<last) return(d, month);
return("Chum",month);
}
fcn tzolkin(date){ // (y,m,d)-->(Int,String)
diff:=Date.deltaDays(Creation,date.xplode()); //--> signed int
rem:=diff % 13;
if(rem<0) rem=13 + rem;
num:=( if(rem<=9) rem + 4 else rem - 9 );
rem=diff % 20;
if(rem<=0) rem=20 + rem;
return(num, sacred[rem-1]);
}
fcn longCount(date){ // (y,m,d) --> (5 Ints)
diff:=Date.deltaDays(Creation,date.xplode()); //--> signed int
diff,baktun := diff + 13*400*360, diff/(400*360);
diff,katun := diff % (400*360), diff/(20*360);
diff,tun := diff % (20*360), diff/360;
diff,winal,kin := diff%360, diff/20, diff % 20;
return(baktun, katun, tun, winal, kin)
}
fcn lord(date){ // (y,m,d) --> String
diff:=Date.deltaDays(Creation,date.xplode()); //--> signed int
rem:=diff % 9;
if(rem<=0) rem=9 + rem;
"G%d".fmt(rem)
}
println(" Gregorian Tzolk'in Haab' Long Lord of");
println(" Date # Name Day Month Count the Night");
println("---------- -------- ------------- -------------- ---------");
#<<<
"
1963-11-21 2004-06-19 2012-12-18 2012-12-21 2019-01-19 2019-03-27
2020-02-29 2020-03-01 2071-05-16
".split()
#<<<
.pump(Void,fcn(date){
ymd:=Date.parseDate(date);
println("%10s %2s %-9s %4s %-10s %-14s %6s".fmt(date,
tzolkin(ymd).xplode(), haab(ymd).xplode(),
longCount(ymd).concat("."),
lord(ymd)));
});
- Output:
Gregorian Tzolk'in Haab' Long Lord of Date # Name Day Month Count the Night ---------- -------- ------------- -------------- --------- 1963-11-21 3 Eb Chum Keh 12.17.10.3.12 G9 2004-06-19 4 Ben 16 Sotz' 12.19.11.6.13 G7 2012-12-18 1 Kaban Chum K'ank'in 12.19.19.17.17 G6 2012-12-21 4 Ajaw 3 K'ank'in 13.0.0.0.0 G9 2019-01-19 1 Ajaw 13 Muwan' 13.0.6.3.0 G6 2019-03-27 3 Manik' Chum Wayeb' 13.0.6.6.7 G1 2020-02-29 4 Kimi 14 K'ayab 13.0.7.5.6 G7 2020-03-01 5 Manik' 15 K'ayab 13.0.7.5.7 G8 2071-05-16 1 Ok 18 Sip 13.2.19.4.10 G9