/* ============================================================================= ctime.c -- time and date support ala' Unix Version 3 -- 1989-01-13 -- D.N. Lynx Crowe ============================================================================= */ #define HAS_ENV 0 /* define non-zero if getenv() exists */ /* * 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-1900 * weekday (0-6, Sun is 0) * day of the year * daylight savings flag * * The routine corrects for daylight savings time and will work in any * time zone provided that "timezone" is adjusted to the difference between * Greenwich and local standard time (measured in seconds). * * In places like Michigan "daylight" must be initialized to 0 to prevent * the conversion to daylight savings time. * * There is a table which accounts for the peculiarities undergone by * daylight savings time in 1974-1975. * * This routine does not work for 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() * * tzset() * * Looks for an environment variable named TZ. * * It should be in the form "ESTn" or "ESTnEDT", * where "n" represents a string of digits with an optional * negative sign (for locations east of Greenwich, England). * * If the variable is present, it will set the external * variables "timezone", "daylight", and "tzname" * appropriately. It is called by localtime, and * may also be called explicitly by the user. */ /* */ #define dysize(A) (((A)%4)? 365: 366) #define void int #include "time.h" long timezone = 8*60*60; int daylight = 0; char *tzname[] = {"PST", "PDT"}; struct tm *gmtime(), *localtime(); char *ctime(), *asctime(); void tzset(); static char cbuf[26]; static int dmsize[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* * The following table is used for 1974 and 1975 and * gives the day number of the first day after the Sunday of the * change. */ static struct { int daylb; int dayle; } daytab[] = { 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ }; /* */ /* ============================================================================= ctime(t) ============================================================================= */ char * ctime(t) long *t; { return(asctime(localtime(t))); } /* */ /* ============================================================================= localtime(tim) ============================================================================= */ struct tm * localtime(tim) long *tim; { register int dayno, daylbegin, daylend; register struct tm *ct; long copyt; tzset(); copyt = *tim - timezone; ct = gmtime(©t); dayno = ct->tm_yday; daylbegin = 119; /* last Sun in Apr */ daylend = 303; /* Last Sun in Oct */ if(ct->tm_year == 74 || ct->tm_year == 75) { daylbegin = daytab[ct->tm_year-74].daylb; daylend = daytab[ct->tm_year-74].dayle; } daylbegin = sunday(ct, daylbegin); daylend = sunday(ct, daylend); if(daylight && (dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) && (daynotm_hour<1))) { copyt += 1*60*60; ct = gmtime(©t); ct->tm_isdst++; } return(ct); } /* */ /* ============================================================================= sunday(t,d) The argument is a 0-origin day number. The value is the day number of the first Sunday on or after the day. ============================================================================= */ static int 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); } /* */ /* ============================================================================= gmtime(tim) ============================================================================= */ struct tm * gmtime(tim) long *tim; { register int d0, d1; long hms, day; static struct 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.tm_sec = hms % 60; d1 = hms / 60; xtime.tm_min = d1 % 60; d1 /= 60; xtime.tm_hour = 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 + 7340036L) % 7; /* * year number */ if(day >= 0) for(d1=70; day >= dysize(d1); d1++) day -= dysize(d1); else for(d1=70; 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; xtime.tm_mday = d0+1; xtime.tm_mon = d1; xtime.tm_isdst = 0; return(&xtime); } /* */ /* ============================================================================= asctime(t) ============================================================================= */ char * asctime(t) struct tm *t; { register char *cp, *ncp; register int *tp; char *ct_numb(); 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); } /* */ /* ============================================================================= ct_numb(cp,n) ============================================================================= */ static char * ct_numb(cp, n) register char *cp; int n; { cp++; if(n >= 10) *cp++ = (n/10)%10 + '0'; else *cp++ = ' '; *cp++ = n%10 + '0'; return(cp); } /* */ /* ============================================================================= tzset() ============================================================================= */ void tzset() { #if HAS_ENV register char *p, *q; register int n; int sign; char *getenv(); if((p = getenv ("TZ")) && *p) { n = 3; q = tzname[0]; do { *q++ = *p? *p++: ' '; } while(--n); if(sign = *p == '-') p++; n = 0; while(*p >= '0' && *p <= '9') n = (n * 10) + *p++ - '0'; if(sign) n = -n; timezone = ((long)(n * 60)) * 60; if(daylight = *p != '\0') { q = tzname[1]; n = 3; do { *q++ = *p? *p++: ' '; } while(--n); } } #endif }