#include <u.h>
#include <libc.h>
static int mtab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int ltab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int
leapyear(int y)
{
if ((0 == y%100 && y%400) || y%4)
return 0;
return 1;
}
static int
mdays(int y, int m)
{
int *tab;
tab = mtab;
if(leapyear(y))
tab = ltab;
return tab[m];
}
static char *wdaytab[] = {
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
0
};
static char *montab[] = {
"jan", "feb", "mar",
"apr", "may", "jun",
"jul", "aug", "sep",
"oct", "nov", "dec",
0
};
int
strton(char *t, char **tab)
{
int i;
char s[4];
if(strlen(t) != 3)
return -1;
for(i=0; i<4; i++)
s[i] = tolower(t[i]);
for(i=0; tab[i]; i++)
if(strcmp(tab[i], s) == 0)
return i;
return -1;
}
int
strtomon(char *s)
{
return strton(s, montab);
}
int
strtowday(char *s)
{
return strton(s, wdaytab);
}
void
tmset(Tm *t, int year, int mon, int whr)
{
memset(t, 0, sizeof *t);
t->year = year - 1900;
t->mon = mon;
t->mday = 1;
t->hour = whr;
strcpy(t->zone, "GMT");
}
long
nthday(int year, int mon, int wday, int whr, int nth)
{
Tm t, *u;
long s, mday;
tmset(&t, year, mon, whr);
u = gmtime(s = tm2sec(&t));
mday = (7-u->wday+wday)%7 + 7*(nth-1);
//fprint(2, "mday = %d, %s", mday, asctime(u));
if(mday>mdays(year, mon))
sysfatal("not %ld days in %s %d", mday, montab[mon], year);
return s+mday*86400;
}
long
lastday(int year, int mon, int wday, int whr)
{
Tm t, *u;
long s, mday, nth, o;
o = whr>0;
tmset(&t, year, mon, whr);
u = gmtime(s = tm2sec(&t));
for(nth = 5; ; nth--){
mday = (7-u->wday+wday)%7 + 7*(nth-1);
if(mday+o>mdays(year, mon))
continue;
return s+mday*86400;
}
}
void
usage(void)
{
fprint(2, "usage: dateof year month wday nth\n");
exits("usage");
}
int
getn(int (*f)(char*), int max, char *s)
{
int i;
if(strlen(s) == 3)
i = f(s);
else
i = atoi(s)-1; /* humans! */
if(i<0 || i>max)
usage();
return i;
}
void
main(int argc, char **argv)
{
long year, month, wday, nth, s, whr;
whr = 2;
ARGBEGIN {
case 'w':
whr = atoi(EARGF(usage()));
break;
default:
usage();
} ARGEND
if(argc != 4)
usage();
year = atoi(*argv++);
month = getn(strtomon, 11, *argv++);
wday = getn(strtowday, 7, *argv++);
if(strcmp(*argv, "last") == 0)
s = lastday(year, month, wday, whr);
else{
nth = atoi(*argv);
if(nth<=0 || nth>5)
usage();
s = nthday(year, month, wday, whr, nth);
}
fprint(1, "%ld\n", s);
fprint(2, "gm = %s", asctime(gmtime(s)));
fprint(2, "local = %s", asctime(localtime(s)));
exits("");
}
|