lib9: rewrite date routines to use /usr/share/zoneinfo directly
This commit is contained in:
parent
1cccddd6b3
commit
f35a04866f
7 changed files with 499 additions and 124 deletions
159
src/lib9/ctime.c
159
src/lib9/ctime.c
|
|
@ -1,21 +1,135 @@
|
||||||
|
/*
|
||||||
|
* This routine converts time as follows.
|
||||||
|
* The epoch is 0000 Jan 1 1970 GMT.
|
||||||
|
* The argument time is in seconds since then.
|
||||||
|
* The localtime(t) entry returns a pointer to an array
|
||||||
|
* containing
|
||||||
|
*
|
||||||
|
* seconds (0-59)
|
||||||
|
* minutes (0-59)
|
||||||
|
* hours (0-23)
|
||||||
|
* day of month (1-31)
|
||||||
|
* month (0-11)
|
||||||
|
* year-1970
|
||||||
|
* weekday (0-6, Sun is 0)
|
||||||
|
* day of the year
|
||||||
|
* daylight savings flag
|
||||||
|
*
|
||||||
|
* The routine gets the daylight savings time from the environment.
|
||||||
|
*
|
||||||
|
* asctime(tvec))
|
||||||
|
* where tvec is produced by localtime
|
||||||
|
* returns a ptr to a character string
|
||||||
|
* that has the ascii time in the form
|
||||||
|
*
|
||||||
|
* \\
|
||||||
|
* Thu Jan 01 00:00:00 GMT 1970n0
|
||||||
|
* 012345678901234567890123456789
|
||||||
|
* 0 1 2
|
||||||
|
*
|
||||||
|
* ctime(t) just calls localtime, then asctime.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
|
|
||||||
static
|
#include "zoneinfo.h"
|
||||||
void
|
|
||||||
ct_numb(char *cp, int n)
|
|
||||||
{
|
|
||||||
|
|
||||||
cp[0] = ' ';
|
static char dmsize[12] =
|
||||||
if(n >= 10)
|
{
|
||||||
cp[0] = (n/10)%10 + '0';
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||||
cp[1] = n%10 + '0';
|
};
|
||||||
|
|
||||||
|
#define dysize ctimedysize
|
||||||
|
static int dysize(int);
|
||||||
|
static void ct_numb(char*, int);
|
||||||
|
|
||||||
|
char*
|
||||||
|
ctime(long t)
|
||||||
|
{
|
||||||
|
return asctime(localtime(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Tm*
|
||||||
|
localtime(long tim)
|
||||||
|
{
|
||||||
|
Tinfo ti;
|
||||||
|
Tm *ct;
|
||||||
|
|
||||||
|
if (zonelookuptinfo(&ti, tim)!=-1) {
|
||||||
|
ct = gmtime(tim+ti.tzoff);
|
||||||
|
strncpy(ct->zone, ti.zone, sizeof ct->zone);
|
||||||
|
ct->zone[sizeof ct->zone-1] = 0;
|
||||||
|
ct->tzoff = ti.tzoff;
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
return gmtime(tim);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tm*
|
||||||
|
gmtime(long tim)
|
||||||
|
{
|
||||||
|
int d0, d1;
|
||||||
|
long hms, day;
|
||||||
|
static Tm xtime;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* break initial number into days
|
||||||
|
*/
|
||||||
|
hms = tim % 86400L;
|
||||||
|
day = tim / 86400L;
|
||||||
|
if(hms < 0) {
|
||||||
|
hms += 86400L;
|
||||||
|
day -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generate hours:minutes:seconds
|
||||||
|
*/
|
||||||
|
xtime.sec = hms % 60;
|
||||||
|
d1 = hms / 60;
|
||||||
|
xtime.min = d1 % 60;
|
||||||
|
d1 /= 60;
|
||||||
|
xtime.hour = d1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* day is the day number.
|
||||||
|
* generate day of the week.
|
||||||
|
* The addend is 4 mod 7 (1/1/1970 was Thursday)
|
||||||
|
*/
|
||||||
|
|
||||||
|
xtime.wday = (day + 7340036L) % 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* year number
|
||||||
|
*/
|
||||||
|
if(day >= 0)
|
||||||
|
for(d1 = 1970; day >= dysize(d1); d1++)
|
||||||
|
day -= dysize(d1);
|
||||||
|
else
|
||||||
|
for (d1 = 1970; day < 0; d1--)
|
||||||
|
day += dysize(d1-1);
|
||||||
|
xtime.year = d1-1900;
|
||||||
|
xtime.yday = d0 = day;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generate month
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(dysize(d1) == 366)
|
||||||
|
dmsize[1] = 29;
|
||||||
|
for(d1 = 0; d0 >= dmsize[d1]; d1++)
|
||||||
|
d0 -= dmsize[d1];
|
||||||
|
dmsize[1] = 28;
|
||||||
|
xtime.mday = d0 + 1;
|
||||||
|
xtime.mon = d1;
|
||||||
|
strcpy(xtime.zone, "GMT");
|
||||||
|
return &xtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
asctime(Tm *t)
|
asctime(Tm *t)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
char *ncp;
|
char *ncp;
|
||||||
static char cbuf[30];
|
static char cbuf[30];
|
||||||
|
|
||||||
|
|
@ -33,12 +147,6 @@ asctime(Tm *t)
|
||||||
ct_numb(cbuf+14, t->min+100);
|
ct_numb(cbuf+14, t->min+100);
|
||||||
ct_numb(cbuf+17, t->sec+100);
|
ct_numb(cbuf+17, t->sec+100);
|
||||||
ncp = t->zone;
|
ncp = t->zone;
|
||||||
for(i=0; i<3; i++)
|
|
||||||
if(ncp[i] == 0)
|
|
||||||
break;
|
|
||||||
for(; i<3; i++)
|
|
||||||
ncp[i] = '?';
|
|
||||||
ncp = t->zone;
|
|
||||||
cbuf[20] = *ncp++;
|
cbuf[20] = *ncp++;
|
||||||
cbuf[21] = *ncp++;
|
cbuf[21] = *ncp++;
|
||||||
cbuf[22] = *ncp;
|
cbuf[22] = *ncp;
|
||||||
|
|
@ -50,9 +158,24 @@ asctime(Tm *t)
|
||||||
return cbuf;
|
return cbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
static
|
||||||
ctime(long t)
|
int
|
||||||
|
dysize(int y)
|
||||||
{
|
{
|
||||||
return asctime(localtime(t));
|
|
||||||
|
if(y%4 == 0 && (y%100 != 0 || y%400 == 0))
|
||||||
|
return 366;
|
||||||
|
return 365;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ct_numb(char *cp, int n)
|
||||||
|
{
|
||||||
|
|
||||||
|
cp[0] = ' ';
|
||||||
|
if(n >= 10)
|
||||||
|
cp[0] = (n/10)%10 + '0';
|
||||||
|
cp[1] = n%10 + '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
100
src/lib9/date.c
100
src/lib9/date.c
|
|
@ -1,100 +0,0 @@
|
||||||
#define NOPLAN9DEFINES
|
|
||||||
#include <u.h>
|
|
||||||
#include <libc.h>
|
|
||||||
#include <stdlib.h> /* setenv etc. */
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
static int
|
|
||||||
dotz(time_t t, char *tzone)
|
|
||||||
{
|
|
||||||
struct tm *gtm;
|
|
||||||
struct tm tm;
|
|
||||||
|
|
||||||
strftime(tzone, 32, "%Z", localtime(&t));
|
|
||||||
tm = *localtime(&t); /* set local time zone field */
|
|
||||||
gtm = gmtime(&t);
|
|
||||||
tm.tm_sec = gtm->tm_sec;
|
|
||||||
tm.tm_min = gtm->tm_min;
|
|
||||||
tm.tm_hour = gtm->tm_hour;
|
|
||||||
tm.tm_mday = gtm->tm_mday;
|
|
||||||
tm.tm_mon = gtm->tm_mon;
|
|
||||||
tm.tm_year = gtm->tm_year;
|
|
||||||
tm.tm_wday = gtm->tm_wday;
|
|
||||||
return t - mktime(&tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tm2Tm(struct tm *tm, Tm *bigtm, int tzoff, char *zone)
|
|
||||||
{
|
|
||||||
memset(bigtm, 0, sizeof *bigtm);
|
|
||||||
bigtm->sec = tm->tm_sec;
|
|
||||||
bigtm->min = tm->tm_min;
|
|
||||||
bigtm->hour = tm->tm_hour;
|
|
||||||
bigtm->mday = tm->tm_mday;
|
|
||||||
bigtm->mon = tm->tm_mon;
|
|
||||||
bigtm->year = tm->tm_year;
|
|
||||||
bigtm->wday = tm->tm_wday;
|
|
||||||
bigtm->tzoff = tzoff;
|
|
||||||
strncpy(bigtm->zone, zone, 3);
|
|
||||||
bigtm->zone[3] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
Tm2tm(Tm *bigtm, struct tm *tm)
|
|
||||||
{
|
|
||||||
/* initialize with current time to get local time zone! (tm_isdst) */
|
|
||||||
time_t t;
|
|
||||||
time(&t);
|
|
||||||
*tm = *localtime(&t);
|
|
||||||
|
|
||||||
tm->tm_sec = bigtm->sec;
|
|
||||||
tm->tm_min = bigtm->min;
|
|
||||||
tm->tm_hour = bigtm->hour;
|
|
||||||
tm->tm_mday = bigtm->mday;
|
|
||||||
tm->tm_mon = bigtm->mon;
|
|
||||||
tm->tm_year = bigtm->year;
|
|
||||||
tm->tm_wday = bigtm->wday;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tm*
|
|
||||||
p9gmtime(long x)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
struct tm tm;
|
|
||||||
static Tm bigtm;
|
|
||||||
|
|
||||||
t = (time_t)x;
|
|
||||||
tm = *gmtime(&t);
|
|
||||||
tm2Tm(&tm, &bigtm, 0, "GMT");
|
|
||||||
return &bigtm;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tm*
|
|
||||||
p9localtime(long x)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
struct tm tm;
|
|
||||||
static Tm bigtm;
|
|
||||||
char tzone[32];
|
|
||||||
|
|
||||||
t = (time_t)x;
|
|
||||||
tm = *localtime(&t);
|
|
||||||
tm2Tm(&tm, &bigtm, dotz(t, tzone), tzone);
|
|
||||||
return &bigtm;
|
|
||||||
}
|
|
||||||
|
|
||||||
long
|
|
||||||
p9tm2sec(Tm *bigtm)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
struct tm tm;
|
|
||||||
char tzone[32];
|
|
||||||
|
|
||||||
Tm2tm(bigtm, &tm);
|
|
||||||
t = mktime(&tm);
|
|
||||||
if(strcmp(bigtm->zone, "GMT") == 0 || strcmp(bigtm->zone, "UCT") == 0){
|
|
||||||
t += dotz(t, tzone);
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -88,7 +88,6 @@ LIB9OFILES=\
|
||||||
create.$O\
|
create.$O\
|
||||||
crypt.$O\
|
crypt.$O\
|
||||||
ctime.$O\
|
ctime.$O\
|
||||||
date.$O\
|
|
||||||
dial.$O\
|
dial.$O\
|
||||||
dirfstat.$O\
|
dirfstat.$O\
|
||||||
dirfwstat.$O\
|
dirfwstat.$O\
|
||||||
|
|
@ -149,6 +148,7 @@ LIB9OFILES=\
|
||||||
syslog.$O\
|
syslog.$O\
|
||||||
sysname.$O\
|
sysname.$O\
|
||||||
time.$O\
|
time.$O\
|
||||||
|
tm2sec.$O\
|
||||||
tokenize.$O\
|
tokenize.$O\
|
||||||
truerand.$O\
|
truerand.$O\
|
||||||
u16.$O\
|
u16.$O\
|
||||||
|
|
@ -158,6 +158,7 @@ LIB9OFILES=\
|
||||||
wait.$O\
|
wait.$O\
|
||||||
waitpid.$O\
|
waitpid.$O\
|
||||||
write.$O\
|
write.$O\
|
||||||
|
zoneinfo.$O\
|
||||||
|
|
||||||
OFILES=\
|
OFILES=\
|
||||||
$LIB9OFILES\
|
$LIB9OFILES\
|
||||||
|
|
@ -193,3 +194,4 @@ testgoogfmt: testfltfmt.$O googfmt.$O $XLIB
|
||||||
testgoogprint: testprint.$O googfmt.$O $XLIB
|
testgoogprint: testprint.$O googfmt.$O $XLIB
|
||||||
$LD -o $target testprint.$O googfmt.$O
|
$LD -o $target testprint.$O googfmt.$O
|
||||||
|
|
||||||
|
ctime.$O tm2sec.$O zoneinfo.$O: zoneinfo.h
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,20 @@
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
opentemp(char *template)
|
opentemp(char *template, int mode)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd, fd1;
|
||||||
|
|
||||||
fd = mkstemp(template);
|
fd = mkstemp(template);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
remove(template);
|
/* reopen for mode */
|
||||||
return fd;
|
fd1 = open(template, mode);
|
||||||
|
if(fd1 < 0){
|
||||||
|
close(fd);
|
||||||
|
remove(template);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return fd1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
110
src/lib9/tm2sec.c
Normal file
110
src/lib9/tm2sec.c
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
#include "zoneinfo.h"
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
Tinfo ti0, ti1, *ti;
|
||||||
|
long secs;
|
||||||
|
int i, yday, year, *d2m;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume the local time zone if zone is not GMT
|
||||||
|
*/
|
||||||
|
if(strcmp(tm->zone, "GMT") != 0) {
|
||||||
|
i = zonelookuptinfo(&ti0, secs);
|
||||||
|
ti = &ti0;
|
||||||
|
if (i != -1)
|
||||||
|
if (ti->tzoff!=0) {
|
||||||
|
/*
|
||||||
|
* to what local time period `secs' belongs?
|
||||||
|
*/
|
||||||
|
if (ti->tzoff>0) {
|
||||||
|
/*
|
||||||
|
* east of GMT; check previous local time transition
|
||||||
|
*/
|
||||||
|
if (ti->t+ti->tzoff > secs)
|
||||||
|
if (zonetinfo(&ti1, i-1)!=-1)
|
||||||
|
ti = &ti1;
|
||||||
|
} else
|
||||||
|
/*
|
||||||
|
* west of GMT; check next local time transition
|
||||||
|
*/
|
||||||
|
if (zonetinfo(&ti1, i+1))
|
||||||
|
if (ti1.t+ti->tzoff < secs)
|
||||||
|
ti = &ti1;
|
||||||
|
// fprint(2, "tt: %ld+%d %ld\n", (long)ti->t, ti->tzoff, (long)secs);
|
||||||
|
secs -= ti->tzoff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(secs < 0)
|
||||||
|
secs = 0;
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
215
src/lib9/zoneinfo.c
Normal file
215
src/lib9/zoneinfo.c
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access local time entries of zoneinfo files.
|
||||||
|
* Formats 0 and 2 are supported, and 4-byte timestamps
|
||||||
|
*
|
||||||
|
* Copyright © 2008 M. Teichgräber
|
||||||
|
* Contributed under the terms of the Lucent Public License 1.02.
|
||||||
|
*/
|
||||||
|
#include "zoneinfo.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
struct Zoneinfo
|
||||||
|
{
|
||||||
|
int timecnt; /* # of transition times */
|
||||||
|
int typecnt; /* # of local time types */
|
||||||
|
int charcnt; /* # of characters of time zone abbreviation strings */
|
||||||
|
|
||||||
|
uchar *ptime;
|
||||||
|
uchar *ptype;
|
||||||
|
uchar *ptt;
|
||||||
|
uchar *pzone;
|
||||||
|
} z;
|
||||||
|
|
||||||
|
static uchar *tzdata;
|
||||||
|
|
||||||
|
static
|
||||||
|
uchar*
|
||||||
|
readtzfile(char *file)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
int fd;
|
||||||
|
Dir *d;
|
||||||
|
|
||||||
|
fd = open(file, OREAD);
|
||||||
|
if (fd<0)
|
||||||
|
return nil;
|
||||||
|
d = dirfstat(fd);
|
||||||
|
if (d==nil)
|
||||||
|
return nil;
|
||||||
|
p = malloc(d->length);
|
||||||
|
if (p!=nil)
|
||||||
|
readn(fd, p, d->length);
|
||||||
|
free(d);
|
||||||
|
close(fd);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
static char *zonefile;
|
||||||
|
void
|
||||||
|
tzfile(char *f)
|
||||||
|
{
|
||||||
|
if (tzdata!=nil) {
|
||||||
|
free(tzdata);
|
||||||
|
tzdata = nil;
|
||||||
|
}
|
||||||
|
z.timecnt = 0;
|
||||||
|
zonefile = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
long
|
||||||
|
get4(uchar *p)
|
||||||
|
{
|
||||||
|
return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TTinfosz = 4+1+1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
parsehead(void)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
int ver;
|
||||||
|
|
||||||
|
ver = tzdata[4];
|
||||||
|
if (ver!=0)
|
||||||
|
if (ver!='2')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
p = tzdata + 4 + 1 + 15;
|
||||||
|
|
||||||
|
z.timecnt = get4(p+3*4);
|
||||||
|
z.typecnt = get4(p+4*4);
|
||||||
|
if (z.typecnt==0)
|
||||||
|
return -1;
|
||||||
|
z.charcnt = get4(p+5*4);
|
||||||
|
z.ptime = p+6*4;
|
||||||
|
z.ptype = z.ptime + z.timecnt*4;
|
||||||
|
z.ptt = z.ptype + z.timecnt;
|
||||||
|
z.pzone = z.ptt + z.typecnt*TTinfosz;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
ttinfo(Tinfo *ti, int tti)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = z.ptype[tti];
|
||||||
|
assert(i<z.typecnt);
|
||||||
|
p = z.ptt + i*TTinfosz;
|
||||||
|
ti->tzoff = get4(p);
|
||||||
|
ti->dlflag = p[4];
|
||||||
|
assert(p[5]<z.charcnt);
|
||||||
|
ti->zone = (char*)z.pzone + p[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
readtimezone(void)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
z.timecnt = 0;
|
||||||
|
switch (zonefile==nil) {
|
||||||
|
default:
|
||||||
|
if ((tmp=getenv("timezone"))!=nil) {
|
||||||
|
tzdata = readtzfile(tmp);
|
||||||
|
free(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zonefile = "/etc/localtime";
|
||||||
|
/* fall through */
|
||||||
|
case 0:
|
||||||
|
tzdata = readtzfile(zonefile);
|
||||||
|
}
|
||||||
|
if (tzdata==nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strncmp("TZif", (char*)tzdata, 4)!=0)
|
||||||
|
goto errfree;
|
||||||
|
|
||||||
|
if (parsehead()==-1) {
|
||||||
|
errfree:
|
||||||
|
free(tzdata);
|
||||||
|
tzdata = nil;
|
||||||
|
z.timecnt = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
tlong
|
||||||
|
gett4(uchar *p)
|
||||||
|
{
|
||||||
|
long l;
|
||||||
|
|
||||||
|
l = get4(p);
|
||||||
|
if (l<0)
|
||||||
|
return 0;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
int
|
||||||
|
zonetinfo(Tinfo *ti, int i)
|
||||||
|
{
|
||||||
|
if (tzdata==nil)
|
||||||
|
readtimezone();
|
||||||
|
if (i<0 || i>=z.timecnt)
|
||||||
|
return -1;
|
||||||
|
ti->t = gett4(z.ptime + 4*i);
|
||||||
|
ttinfo(ti, i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
zonelookuptinfo(Tinfo *ti, tlong t)
|
||||||
|
{
|
||||||
|
uchar *p;
|
||||||
|
int i;
|
||||||
|
tlong oldtt, tt;
|
||||||
|
|
||||||
|
if (tzdata==nil)
|
||||||
|
readtimezone();
|
||||||
|
oldtt = 0;
|
||||||
|
p = z.ptime;
|
||||||
|
for (i=0; i<z.timecnt; i++) {
|
||||||
|
tt = gett4(p);
|
||||||
|
if (t<tt)
|
||||||
|
break;
|
||||||
|
oldtt = tt;
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
if (i>0) {
|
||||||
|
ttinfo(ti, i-1);
|
||||||
|
ti->t = oldtt;
|
||||||
|
// fprint(2, "t:%ld off:%d dflag:%d %s\n", (long)ti->t, ti->tzoff, ti->dlflag, ti->zone);
|
||||||
|
return i-1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
zonedump(int fd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uchar *p;
|
||||||
|
tlong t;
|
||||||
|
Tinfo ti;
|
||||||
|
|
||||||
|
if (tzdata==nil)
|
||||||
|
readtimezone();
|
||||||
|
p = z.ptime;
|
||||||
|
for (i=0; i<z.timecnt; i++) {
|
||||||
|
t = gett4(p);
|
||||||
|
ttinfo(&ti, i);
|
||||||
|
fprint(fd, "%ld\t%d\t%d\t%s\n", (long)t, ti.tzoff, ti.dlflag, ti.zone);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/lib9/zoneinfo.h
Normal file
19
src/lib9/zoneinfo.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#define zonetinfo _p9zonetinfo
|
||||||
|
#define zonedump _p9zonedump
|
||||||
|
#define zonelookuptinfo _p9zonelookuptinfo
|
||||||
|
|
||||||
|
typedef long tlong;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
struct Tinfo
|
||||||
|
{
|
||||||
|
long t;
|
||||||
|
int tzoff;
|
||||||
|
int dlflag;
|
||||||
|
char *zone;
|
||||||
|
} Tinfo;
|
||||||
|
|
||||||
|
extern int zonelookuptinfo(Tinfo*, tlong);
|
||||||
|
extern int zonetinfo(Tinfo*, int);
|
||||||
|
extern void zonedump(int fd);
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue