diff -r d45cfe9072cd sys/src/cmd/upas/imap4d/date.c --- a/sys/src/cmd/upas/imap4d/date.c Sat May 30 13:03:05 2020 +0200 +++ b/sys/src/cmd/upas/imap4d/date.c Sat May 30 19:08:04 2020 -0700 @@ -1,142 +1,10 @@ #include "imap4d.h" -static char *wdayname[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static char *monname[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -/* - * zone : [A-Za-z][A-Za-z][A-Za-z] some time zone names - * | [A-IK-Z] military time; rfc1123 says the rfc822 spec is wrong. - * | "UT" universal time - * | [+-][0-9][0-9][0-9][0-9] - * zones is the rfc-822 list of time zone names - */ -static Namedint zones[] = -{ - {"A", -1 * 3600}, - {"B", -2 * 3600}, - {"C", -3 * 3600}, - {"CDT", -5 * 3600}, - {"CST", -6 * 3600}, - {"D", -4 * 3600}, - {"E", -5 * 3600}, - {"EDT", -4 * 3600}, - {"EST", -5 * 3600}, - {"F", -6 * 3600}, - {"G", -7 * 3600}, - {"GMT", 0}, - {"H", -8 * 3600}, - {"I", -9 * 3600}, - {"K", -10 * 3600}, - {"L", -11 * 3600}, - {"M", -12 * 3600}, - {"MDT", -6 * 3600}, - {"MST", -7 * 3600}, - {"N", +1 * 3600}, - {"O", +2 * 3600}, - {"P", +3 * 3600}, - {"PDT", -7 * 3600}, - {"PST", -8 * 3600}, - {"Q", +4 * 3600}, - {"R", +5 * 3600}, - {"S", +6 * 3600}, - {"T", +7 * 3600}, - {"U", +8 * 3600}, - {"UT", 0}, - {"V", +9 * 3600}, - {"W", +10 * 3600}, - {"X", +11 * 3600}, - {"Y", +12 * 3600}, - {"Z", 0}, -}; - -static void -zone2tm(Tm *tm, char *s) -{ - int i; - Tm aux, *atm; - - if(*s == '+' || *s == '-'){ - i = strtol(s, &s, 10); - tm->tzoff = (i/100)*3600 + i%100; - strncpy(tm->zone, "", 4); - return; - } - - /* - * look it up in the standard rfc822 table - */ - strncpy(tm->zone, s, 3); - tm->zone[3] = 0; - tm->tzoff = 0; - for(i = 0; i < nelem(zones); i++){ - if(cistrcmp(zones[i].name, s) == 0){ - tm->tzoff = zones[i].v; - return; - } - } - - /* - * one last try: look it up in the current local timezone - * probe a couple of times to get daylight/standard time change. - */ - aux = *tm; - memset(aux.zone, 0, 4); - aux.hour--; - for(i = 0; i < 2; i++){ - atm = localtime(tm2sec(&aux)); - if(cistrcmp(tm->zone, atm->zone) == 0){ - tm->tzoff = atm->tzoff; - return; - } - aux.hour++; - } - - strncpy(tm->zone, "GMT", 4); - tm->tzoff = 0; -} - -/* - * hh[:mm[:ss]] - */ -static void -time2tm(Tm *tm, char *s) -{ - tm->hour = strtoul(s, &s, 10); - if(*s++ != ':') - return; - tm->min = strtoul(s, &s, 10); - if(*s++ != ':') - return; - tm->sec = strtoul(s, &s, 10); -} - -static int -dateindex(char *d, char **tab, int n) -{ - int i; - - for(i = 0; i < n; i++) - if(cistrcmp(d, tab[i]) == 0) - return i; - return -1; -} - int imap4date(Tm *tm, char *date) { - char *flds[4]; - - if(getfields(date, flds, 3, 0, "-") != 3) + if(tmparse(tm, "DD-MM-YYYY", date, nil) == nil) return 0; - - tm->mday = strtol(flds[0], nil, 10); - tm->mon = dateindex(flds[1], monname, 12); - tm->year = strtol(flds[2], nil, 10) - 1900; return 1; } @@ -146,29 +14,11 @@ ulong imap4datetime(char *date) { - char *flds[4], *sflds[4]; - ulong t; Tm tm; - if(getfields(date, flds, 4, 0, " ") != 3) + if(tmparse(&tm, "DD-MM-YYYY hh:mm:ss ?ZZZ", date, nil) == nil) return ~0; - - if(!imap4date(&tm, flds[0])) - return ~0; - - if(getfields(flds[1], sflds, 3, 0, ":") != 3) - return ~0; - - tm.hour = strtol(sflds[0], nil, 10); - tm.min = strtol(sflds[1], nil, 10); - tm.sec = strtol(sflds[2], nil, 10); - - strcpy(tm.zone, "GMT"); - tm.yday = 0; - t = tm2sec(&tm); - zone2tm(&tm, flds[2]); - t -= tm.tzoff; - return t; + return tm.abs; } /* @@ -181,85 +31,16 @@ Tm* date2tm(Tm *tm, char *date) { - char *flds[7], *s, dstr[64]; - int n; - Tm gmt, *atm; + char **f, *fmts[] = { + "?W ?DD ?MMM ?YYYY hh:mm:ss ?Z", + "?W, ?DD ?MMM ?YYYY hh:mm:ss ?Z", + "?W, ?DD ?MMM hh:mm:ss ?Z ?YYYY", + "?MMM hh:mm:ss ?Z ?YYYY", + nil + }; + for(f = fmts; *f != nil; f++) + if(tmparse(tm, *f, date, nil) != nil) + return tm; + return nil; +} - /* - * default date is Thu Jan 1 00:00:00 GMT 1970 - */ - tm->wday = 4; - tm->mday = 1; - tm->mon = 1; - tm->hour = 0; - tm->min = 0; - tm->sec = 0; - tm->year = 70; - strcpy(tm->zone, "GMT"); - tm->tzoff = 0; - - strncpy(dstr, date, sizeof dstr); - dstr[sizeof dstr - 1] = 0; - n = tokenize(dstr, flds, 7); - if(n != 6 && n != 5) - return nil; - - if(n == 5){ - for(n = 5; n >= 1; n--) - flds[n] = flds[n - 1]; - n = 5; - }else{ - /* - * Wday[,] - */ - s = strchr(flds[0], ','); - if(s != nil) - *s = 0; - tm->wday = dateindex(flds[0], wdayname, 7); - if(tm->wday < 0) - return nil; - } - - /* - * check for the two major formats: - * Month first or day first - */ - tm->mon = dateindex(flds[1], monname, 12); - if(tm->mon >= 0){ - tm->mday = strtoul(flds[2], nil, 10); - time2tm(tm, flds[3]); - zone2tm(tm, flds[4]); - tm->year = strtoul(flds[5], nil, 10); - if(strlen(flds[5]) > 2) - tm->year -= 1900; - }else{ - tm->mday = strtoul(flds[1], nil, 10); - tm->mon = dateindex(flds[2], monname, 12); - if(tm->mon < 0) - return nil; - tm->year = strtoul(flds[3], nil, 10); - if(strlen(flds[3]) > 2) - tm->year -= 1900; - time2tm(tm, flds[4]); - zone2tm(tm, flds[5]); - } - - if(n == 5){ - gmt = *tm; - strncpy(gmt.zone, "", 4); - gmt.tzoff = 0; - atm = gmtime(tm2sec(&gmt)); - tm->wday = atm->wday; - }else{ - /* - * Wday[,] - */ - s = strchr(flds[0], ','); - if(s != nil) - *s = 0; - tm->wday = dateindex(flds[0], wdayname, 7); - if(tm->wday < 0) - return nil; - } - return tm; -}