/* Like datefmt, but for the Mayan calendars */
/* Needs cleanup */
#include <u.h>
#include <libc.h>
/* Unix epoch, Jan 1, 1970, is "13 Chikchan 3 K'ank'in, 12.17.16.7.5" */
/* Tzolk'in: 260-day count */
/* 20 names, 13 numbers, both incrementing daily */
/* Numbers used were 1-13 */
char *tzolkin_d[]=
{
"Imix'", "Ik'", "Ak'b'al", "K'an", "Chikchan",
"Kimi", "Manik'", "lamat", "Muluk", "Ok",
"Chuwen", "Eb'", "B'en", "Ix", "Men",
"K'ib'", "Kab'an", "Etz'nab'", "Kawak", "Ajaw",
};
/* Haab': 365-day count */
/* 18 months of 20 days, plus five days */
/* Days of the month went from 0-19 (per most research) */
char *haab_m[]=
{
"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'",
};
/* Long Count */
/* Most inscriptions usually used just the first 5 places */
/* K'in (day) */
/* Winal is 20 K'in */
/* Tun is 18 Winal */
/* K'atun is 20 Tun */
/* B'ak'tun is 20 K'atun */
/* Piktun is 20 B'ak'tun */
/* Kalabtun is 20 Piktun */
/* K'inchiltun is 20 Kalabtun */
/* Alautun is 20 K'inchiltun */
/* Codes: aAbB dD H kK LmMnN rR tTuU wW X Z % */
typedef
struct Lc
{
int kin;
int winal;
int tun;
int katun;
int baktun;
int piktun;
int kalabtun;
int kinchiltun;
int alautun;
} Lc;
typedef
struct Maya_t
{
int trecena;
int name;
int hdn; /* Haab' day number; internal only. */
int number;
int month;
Lc longcount;
} Maya_t;
char *format_t(char *, Maya_t);
Maya_t* init(long);
ulong now;
void
usage(void)
{
fprint(2, "usage: %s [-t seconds] format\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
Maya_t *now_m;
now = time(0);
ARGBEGIN{
case 't':
now = strtoul(EARGF(usage()), 0, 0);
break;
default:
usage();
}ARGEND
if(! argc == 1)
usage();
now_m = init(now);
print("%s", format_t(argv[0], *now_m));
exits(0);
}
/* Generate a Maya_t; analogous to /sys/src/libc/9sys/ctime.c:/^gmtime */
Maya_t*
init(long tim)
{
long day;
long d_winal, d_tun, d_katun, d_baktun; /* Days per winal, &c. */
static Maya_t mt;
/*
* break initial number into days
*/
day = tim / 86400L;
if(tim % 86400L < 0)
day -= 1;
d_winal=20;
d_tun=20*18;
d_katun=20*18*20;
d_baktun=20*18*20*20;
mt.trecena=((12+day)%13)+1; /* 1-13, not 0-12 */
mt.name=(4+day)%20;
mt.hdn=(263+day)%365;
mt.number=(mt.hdn)%20;
mt.month=(((mt.hdn)/20))%19;
/* Pick & set an epoch. Make sure mt.longcount & day match. */
mt.longcount.alautun=0;
mt.longcount.kinchiltun=0;
mt.longcount.kalabtun=0;
mt.longcount.piktun=0;
mt.longcount.baktun=12;
mt.longcount.katun=17;
mt.longcount.tun=16;
mt.longcount.winal=7;
mt.longcount.kin=5;
if(day>0) {
mt.longcount.kin = (mt.longcount.kin + day)%20;
day -= mt.longcount.kin-5;
mt.longcount.winal = (mt.longcount.winal + day/d_winal)%18;
day -= (mt.longcount.winal-7)*d_winal;
mt.longcount.tun = (mt.longcount.tun + day/d_tun)%20;
day -= (mt.longcount.tun-16)*d_tun;
mt.longcount.katun = (mt.longcount.katun + day/d_katun)%20;
day -= (mt.longcount.katun-17)*d_katun;
mt.longcount.baktun = (mt.longcount.baktun + day/d_baktun)%20;
// day -= (mt.longcount.baktun-12)*d_baktun;
} else if(day<0) {
print("NEGATIVE DAY: BOGUS VALUES! ");
;
}
return &mt;
}
char *
format_t(char *format, Maya_t m)
{
char *outb;
int i;
outb="";
for(i = 0; i < strlen(format); i++){
if(format[i] != '%') {
outb=smprint("%s%c", outb, format[i]);
}
else switch(format[++i]){
/* Tzolk'in dates "1 Imix'", "12 Men", &c */
case 'T':
outb=smprint("%s%s", outb, format_t("%R %N", m));
break;
case 'r':
outb=smprint("%s%.2d", outb, m.trecena);
break;
case 'R':
outb=smprint("%s%d", outb, m.trecena);
break;
// case 'n':
// outb=smprint("%s%.2d", outb, m.name);
// break;
case 'N':
outb=smprint("%s%s", outb, tzolkin_d[m.name]);
break;
/* Haab' dates "0 Pop", "3 Wo", &c */
case 'H':
outb=smprint("%s%s", outb, format_t("%D %M", m));
break;
case 'd':
outb=smprint("%s%.2d", outb, m.number);
break;
case 'D':
outb=smprint("%s%d", outb, m.number);
break;
case 'm':
outb=smprint("%s%.2d", outb, m.month);
break;
case 'M':
outb=smprint("%s%s", outb, haab_m[m.month]);
break;
/* Written together as "1 Imix' 0 Pop", "12 Men 3 Wo", &c */
case 'X':
outb=smprint("%s%s", outb, format_t("%T %H", m));
break;
/* Long Count and components */
case 'L':
outb=smprint("%s%s", outb, format_t("%B.%A.%U.%W.%K", m));
break;
case 'k':
outb=smprint("%s%.2d", outb, m.longcount.kin);
break;
case 'K':
outb=smprint("%s%d", outb, m.longcount.kin);
break;
case 'w':
outb=smprint("%s%.2d", outb, m.longcount.winal);
break;
case 'W':
outb=smprint("%s%d", outb, m.longcount.winal);
break;
case 'u':
outb=smprint("%s%.2d", outb, m.longcount.tun);
break;
case 'U':
outb=smprint("%s%d", outb, m.longcount.tun);
break;
case 'a':
outb=smprint("%s%.2d", outb, m.longcount.katun);
break;
case 'A':
outb=smprint("%s%d", outb, m.longcount.katun);
break;
case 'b':
outb=smprint("%s%.2d", outb, m.longcount.baktun);
break;
case 'B':
outb=smprint("%s%d", outb, m.longcount.baktun);
break;
/* Need higher-order long count places */
/* Everything together. How were these really written? */
case 'Z':
outb=smprint("%s%s", outb, format_t("%X %L", m));
break;
case '+':
outb=smprint("%s%s\n", outb, format_t("%Z", m));
break;
/* Literals and others */
case ' ':
outb=smprint("%s%s", outb, "% ");
break;
case '%':
outb=smprint("%s%s", outb, "%");
break;
case 'n':
outb=smprint("%s%s", outb, "\n");
break;
case 't':
outb=smprint("%s%s", outb, " ");
break;
default:
break;
}
}
return outb;
}
|