diff options
author | Ori Bernstein <ori@eigenstate.org> | 2020-08-09 18:58:44 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2020-08-09 18:58:44 -0700 |
commit | 56e869ac7004a635a7d63596ee751275484f28c3 (patch) | |
tree | 6abb2068c51ed8d44b7abebe7f633952cedcb92e /sys/src/libc/9sys/tm2sec.c | |
parent | 3ba1d83d2026ebac616ab17a2126df97c0a7a24c (diff) |
libc: new date apis
The current date and time APIs on Plan 9 are not good. They're
inflexible, non-threadsafe, and don't expose timezone information.
This commit adds new time APIs that allow parsing arbitrary
dates, work from multiple threads, and can handle timezones
effectively.
Diffstat (limited to 'sys/src/libc/9sys/tm2sec.c')
-rw-r--r-- | sys/src/libc/9sys/tm2sec.c | 197 |
1 files changed, 3 insertions, 194 deletions
diff --git a/sys/src/libc/9sys/tm2sec.c b/sys/src/libc/9sys/tm2sec.c index 20bebd0c8..8b3a9d967 100644 --- a/sys/src/libc/9sys/tm2sec.c +++ b/sys/src/libc/9sys/tm2sec.c @@ -1,202 +1,11 @@ #include <u.h> #include <libc.h> -#define TZSIZE 150 -static void readtimezone(void); -static int rd_name(char**, char*); -static int rd_long(char**, long*); -static -struct -{ - char stname[4]; - char dlname[4]; - long stdiff; - long dldiff; - long dlpairs[TZSIZE]; -} timezone; - -#define SEC2MIN 60L -#define SEC2HOUR (60L*SEC2MIN) -#define SEC2DAY (24L*SEC2HOUR) - -/* - * days per month plus days/year - */ -static int dmsize[] = -{ - 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; -static int ldmsize[] = -{ - 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/* - * return the days/month for the given year - */ -static int * -yrsize(int y) -{ - if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0)) - return ldmsize; - else - return dmsize; -} - -/* - * compute seconds since Jan 1 1970 GMT - * and convert to our timezone. - */ long tm2sec(Tm *tm) { - long secs, *p; - int i, yday, year, *d2m; - - if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0) - readtimezone(); - secs = 0; - - /* - * seconds per year - */ - year = tm->year + 1900; - for(i = 1970; i < year; i++){ - d2m = yrsize(i); - secs += d2m[0] * SEC2DAY; - } - - /* - * if mday is set, use mon and mday to compute yday - */ - if(tm->mday){ - yday = 0; - d2m = yrsize(year); - for(i=0; i<tm->mon; i++) - yday += d2m[i+1]; - yday += tm->mday-1; - }else{ - yday = tm->yday; - } - secs += yday * SEC2DAY; - - /* - * hours, minutes, seconds - */ - secs += tm->hour * SEC2HOUR; - secs += tm->min * SEC2MIN; - secs += tm->sec; - - /* - * Only handles zones mentioned in /env/timezone, - * but things get too ambiguous otherwise. - */ - if(strcmp(tm->zone, timezone.stname) == 0) - secs -= timezone.stdiff; - else if(strcmp(tm->zone, timezone.dlname) == 0) - secs -= timezone.dldiff; - else if(tm->zone[0] == 0){ - secs -= timezone.dldiff; - for(p = timezone.dlpairs; *p; p += 2) - if(secs >= p[0] && secs < p[1]) - break; - if(*p == 0){ - secs += timezone.dldiff; - secs -= timezone.stdiff; - } - } - return secs; -} - -static -void -readtimezone(void) -{ - char buf[TZSIZE*11+30], *p; - int i; - - memset(buf, 0, sizeof(buf)); - i = open("/env/timezone", 0); - if(i < 0) - goto error; - if(read(i, buf, sizeof(buf)) >= sizeof(buf)) - goto error; - close(i); - p = buf; - if(rd_name(&p, timezone.stname)) - goto error; - if(rd_long(&p, &timezone.stdiff)) - goto error; - if(rd_name(&p, timezone.dlname)) - goto error; - if(rd_long(&p, &timezone.dldiff)) - goto error; - for(i=0; i<TZSIZE; i++) { - if(rd_long(&p, &timezone.dlpairs[i])) - goto error; - if(timezone.dlpairs[i] == 0) - return; - } - -error: - timezone.stdiff = 0; - strcpy(timezone.stname, "GMT"); - timezone.dlpairs[0] = 0; -} - -static int -rd_name(char **f, char *p) -{ - int c, i; - - for(;;) { - c = *(*f)++; - if(c != ' ' && c != '\n') - break; - } - for(i=0; i<3; i++) { - if(c == ' ' || c == '\n') - return 1; - *p++ = c; - c = *(*f)++; - } - if(c != ' ' && c != '\n') - return 1; - *p = 0; - return 0; -} - -static int -rd_long(char **f, long *p) -{ - int c, s; - long l; + Tm tt; - s = 0; - for(;;) { - c = *(*f)++; - if(c == '-') { - s++; - continue; - } - if(c != ' ' && c != '\n') - break; - } - if(c == 0) { - *p = 0; - return 0; - } - l = 0; - for(;;) { - if(c == ' ' || c == '\n') - break; - if(c < '0' || c > '9') - return 1; - l = l*10 + c-'0'; - c = *(*f)++; - } - if(s) - l = -l; - *p = l; - return 0; + tt = *tm; + return tmnorm(&tt); } |