home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) mktime.c 3.0 " __DATE__ " HJR";
-
- /* mktime.c (c) Copyright 1990 H.Rogers */
-
- #include <time.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
-
- static unsigned int __tmonth[12] =
- {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
- static struct tm __tz[1] = /* time struct */
- {
- {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, ""}
- };
-
- /* Time zones are "[TZNAME][H][:M][DSTNAME]" where H:M gives the time *west*
- * of GMT for the timezone. If DSTNAME appears then the time zone follows
- * DST rules according to DSTNAME. Examples:
- *
- * "EST5EDT" USA Eastern time zone
- * "CST6CDT" USA Central time zone
- * "NFLDT3:30NFLD" Newfoundland time (1:30 ahead of Eastern)
- * "OZCST-9:30" Australian Central time zone (no DST)
- *
- * DST is currently unimplemented: Other implementations involve very nasty
- * code in order to cater for exception years (e.g. USA 1972). Also most
- * assume USA rules for DST (which have changed 3 times since 1970), not UK
- * rules (which have changed more often and are more complex :-( ). It's
- * simpler to rely on the SysAdmin changing the system clock twice a year
- * according to local custom. Leap seconds and the century offset are ignored,
- * but the routines are correct to within a second till at least 2038... */
-
- int timezone = 0;
-
- void
- tzset (void)
- {
- char *z;
- register int i;
-
- if (!(z = getenv ("TZ")))
- z = "GMT0UK"; /* default to GMT/UKDST */
-
- i = 0;
- while (isalpha (*z))
- {
- if (i < 3)
- {
- __tz->tm_zone[i] = *z;
- i++;
- }
- z++;
- }
- __tz->tm_zone[i] = 0;
-
- i = (int) strtol (z, &z, 10) * 3600;
- if (*z == ':')
- {
- z++;
- i += (int) strtol (z, &z, 10) * 60;
- }
-
- __tz->tm_gmtoff = timezone = i;
- }
-
- static struct tm *__mktm (register time_t);
-
- struct tm *
- gmtime (register const time_t * tp)
- {
- if (!(__tz->tm_zone[0]))
- tzset ();
-
- return (__mktm (*tp));
- }
-
- struct tm *
- localtime (register const time_t * tp)
- {
- if (!(__tz->tm_zone[0]))
- tzset ();
-
- return (__mktm ((*tp) - __tz->tm_gmtoff));
- }
-
- static struct tm *
- __mktm (register time_t tm)
- {
- register struct tm *t = __tz;
- register time_t i, j, k;
-
- t->tm_isdst = -1;
-
- t->tm_wday = (tm / 86400 + 4) % 7; /* 1st Jan 1970 = Thursday */
-
- t->tm_sec = tm % 60;
- tm /= 60;
- t->tm_min = tm % 60;
- tm /= 60;
- t->tm_hour = tm % 24;
- tm /= 24;
-
- i = (365 << 1); /* two years */
-
- if (tm >= i) /* >= 1972 */
- {
- j = (tm - i) / 1461;
- tm -= i + j * 1461;
- k = tm ? ((tm - 1) / 365) : 0;
- if (k)
- {
- tm -= 1 + k * 365;
- __tmonth[1] = 28;
- }
- else
- __tmonth[1] = 29; /* Feb. hath 29 days in a leap year */
- k += 2 + (j << 2);
- }
- else
- /* < 1972 */
- {
- k = tm / 365;
- tm -= k * 365;
- __tmonth[1] = 28;
- }
-
- t->tm_year = k + 70;
- t->tm_yday = tm;
-
- k = tm;
- j = 0;
- while (k >= (i = __tmonth[j]))
- k -= i, j++;
-
- t->tm_mon = j;
- t->tm_mday = k + 1;
-
- return (t);
- }
-
- time_t
- mktime (register struct tm * t)
- {
- register time_t r;
-
- if ((t->tm_year - 70) < 0)
- return ((time_t) - 1);
-
- r = t->tm_year - 70;
-
- if (r < 2)
- r = r * 365;
- else
- {
- register int i, j;
-
- i = (r - 2) & 3;
- j = ((r - 2) >> 2) * 1461;
- if (i)
- {
- r = (365 << 1) + j + 1 + i * 365;
- }
- else
- r = (365 << 1) + j;
- }
-
- r += t->tm_yday;
- r = r * 24 + t->tm_hour;
- r = r * 60 + t->tm_min;
- r = r * 60 + t->tm_sec;
-
- r += t->tm_gmtoff; /* mktime() is passed a localtime() struct */
-
- return (r);
- }
-