#include #include 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(""); }