/* * 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 calls the system to determine the local * timezone and whether Daylight Saving Time is permitted locally. * (DST is then determined by the current US standard rules) * There is a table that accounts for the peculiarities * undergone by daylight time in 1974-1975. * * The routine does not work * in Saudi Arabia which runs on Solar time. * * 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 1970n0\\ * 01234567890123456789012345 * 0 1 2 * * ctime(t) just calls localtime, then asctime. */ #include <time.h> #include <sys/types.h> #include <sys/timeb.h> static char cbuf[26]; static int dmsize[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; #define NDAYTAB 10 static int ndaytab; static struct daytab { unsigned char ybeg; /* year-1900 */ unsigned char yend; unsigned char obeg; /* offset from sunday */ unsigned char oend; short dbeg; short dend; } daytab[NDAYTAB]; struct tm *gmtime(); char *ct_numb(); struct tm *localtime(); char *ctime(); char *ct_num(); char *asctime(); char * ctime(t) long *t; { return(asctime(localtime(t))); } struct tm * localtime(tim) long *tim; { register int dayno; register struct tm *ct; register daylbegin, daylend; int boff, eoff; register int i; register int incr; register int tmp; long copyt; struct timeb systime; ftime(&systime); copyt = *tim - (long)systime.timezone*60; ct = gmtime(©t); if (systime.dstflag == 0) return (ct); dayno = ct->tm_yday; daylbegin = 999; /* default: no dst */ daylend = 999; incr = 1*60*60; boff = eoff = 0; rdaytab(); for (i = 0; i < ndaytab; i++) if (daytab[i].ybeg <= ct->tm_year && ct->tm_year <= daytab[i].yend) { daylbegin = daytab[i].dbeg; daylend = daytab[i].dend; boff = daytab[i].obeg; eoff = daytab[i].oend; break; } if (daylbegin > daylend) { tmp = daylbegin; daylbegin = daylend; daylend = tmp; copyt += incr; incr = -incr; } daylbegin = sunday(ct, daylbegin)+boff; daylend = sunday(ct, daylend)+eoff; if ((dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) && (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) { copyt += incr; ct = gmtime(©t); ct->tm_isdst++; } return(ct); } /* * The argument is a 0-origin day number. * The value is the day number of the last * Sunday before or after the day. */ static sunday(t, d) register struct tm *t; register int d; { if (d >= 58) d += dysize(t->tm_year) - 365; return(d - (d - t->tm_yday + t->tm_wday + 700) % 7); } struct tm * gmtime(tim) long *tim; { register int d0, d1; long hms, day; register int *tp; static struct tm xtime; /* * break initial number into days */ hms = *tim % 86400; day = *tim / 86400; if (hms<0) { hms += 86400; day -= 1; } tp = (int *)&xtime; /* * generate hours:minutes:seconds */ *tp++ = hms%60; d1 = hms/60; *tp++ = d1%60; d1 /= 60; *tp++ = d1; /* * day is the day number. * generate day of the week. * The addend is 4 mod 7 (1/1/1970 was Thursday) */ xtime.tm_wday = (day+7340036)%7; /* * year number */ /* in 400 years there are 97*366+303*365=146097 days (40 bits and up)*/ if(day>=0) { for(d1 = 70; day >= 146097; d1 += 400) day -= 146097; for(; day >= dysize(d1); d1++) day -= dysize(d1); } else { for(d1 = 70; day <= -146097; d1 -= 400) day += 146097; for(; day < 0; d1--) day += dysize(d1-1); /* ! */ } xtime.tm_year = d1; xtime.tm_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; *tp++ = d0+1; *tp++ = d1; xtime.tm_isdst = 0; return(&xtime); } char * asctime(t) struct tm *t; { register char *cp, *ncp; register int *tp; cp = cbuf; for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday]; cp = cbuf; *cp++ = *ncp++; *cp++ = *ncp++; *cp++ = *ncp++; cp++; tp = &t->tm_mon; ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; *cp++ = *ncp++; *cp++ = *ncp++; *cp++ = *ncp++; cp = ct_numb(cp, *--tp); cp = ct_numb(cp, *--tp+100); cp = ct_numb(cp, *--tp+100); cp = ct_numb(cp, *--tp+100); if (t->tm_year>=100) { cp[1] = '2'; cp[2] = '0'; } cp += 2; cp = ct_numb(cp, t->tm_year+100); return(cbuf); } dysize(y) { if((y%4) == 0) return(366); return(365); } static char * ct_numb(cp, n) register char *cp; { cp++; if (n>=10) *cp++ = (n/10)%10 + '0'; else *cp++ = ' '; *cp++ = n%10 + '0'; return(cp); } #include <ctype.h> /* * read the file of daylight savings time boundaries * it looks like * 1971 1983 32 0 317 1 * to mean that for years 1971-1983, dst starts the first sunday after * day 32, and ends the first monday after day 317 */ #define BUFSZ 1024 #define DSTFILE "/lib/dst" static rdaytab() { static int doneit; int fd; char buf[BUFSZ]; char *p; register int i; char *rdline(); if (doneit++) return; if ((fd = open(DSTFILE, 0)) < 0) return; i = 0; while ((p = rdline(fd, buf)) != 0) if (dtparse(p, &daytab[i])) if (++i >= NDAYTAB) break; ndaytab = i; close(fd); } dtparse(p, dp) register char *p; register struct daytab *dp; { short s; char *gint(); if ((p = gint(p, &s)) == 0) return (0); if (s < 1900) dp->ybeg = 0; else if (s > (1900+255)) dp->ybeg = 255; else dp->ybeg = s - 1900; if ((p = gint(p, &s)) == 0) return (0); if (s < 1900) dp->yend = 0; else if (s > (1900+255)) dp->yend = 255; else dp->yend = s - 1900; if ((p = gint(p, &dp->dbeg)) == 0) return (0); if ((p = gint(p, &s)) == 0) return (0); dp->obeg = s; if ((p = gint(p, &dp->dend)) == 0) return (0); if ((p = gint(p, &s)) == 0) return (0); dp->oend = s; return (1); } static char * gint(p, sp) register char *p; register short *sp; { register int i; while (isspace(*p)) p++; if (!isdigit(*p)) return (0); i = 0; while (isdigit(*p)) i = (i*10) + *p++ - '0'; *sp = i; return (p); } static char * rdline(fd, buf) int fd; char *buf; { register char *p, *q; static char *lastp; static char *endp; int n; if (lastp == 0 || lastp >= endp) { if ((n = read(fd, buf, BUFSZ)) <= 0) return (0); lastp = buf; endp = &buf[n]; } for (p = lastp; p < endp && *p != '\n'; p++) ; if (p < endp || lastp == buf) { *p++ = 0; q = lastp; lastp = p; return (q); } /* * unfinished line at end of buffer. try again. */ q = lastp; p = buf; while (q < endp) *p++ = *q++; if ((n = read(fd, p, BUFSZ - (p-buf))) <= 0) return (0); endp = &p[n]; for (; p < endp && *p != '\n'; p++) ; if (p >= endp) --p; /* too bad */ *p++ = 0; lastp = p; return (buf); }