added table for time-zone determination
authoreck <none@none>
Fri, 12 Oct 1990 14:48:55 +0000 (14:48 +0000)
committereck <none@none>
Fri, 12 Oct 1990 14:48:55 +0000 (14:48 +0000)
lang/cem/libcc.ansi/time/misc.c

index 6f7ab19..542323e 100644 (file)
@@ -44,7 +44,7 @@ void _ftime(struct timeb *bp);
  * right value from the system. TZ is the only help.
  */
 static char ntstr[TZ_LEN + 1] = "GMT"; /* string for normal time */
-static char dststr[TZ_LEN + 1] = "GMT";        /* string for daylight saving */
+static char dststr[TZ_LEN + 1] = "GDT";        /* string for daylight saving */
 
 long   _timezone = 0;
 long   _dst_off = 60 * 60;
@@ -84,6 +84,96 @@ const int _ytab[2][12] = {
                { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
        };
 
+#if    !defined(_POSIX_SOURCE) && !defined(__USG)
+#define        USE_TABLE       1
+#endif
+
+#if    USE_TABLE
+static int usetable = 1;
+
+typedef struct table {
+       const char *tz_name;
+       const int daylight;
+       const long zoneoffset;
+} TABLE;
+
+#define HOUR(x)        ((x) * 60*60)
+
+static TABLE TimezoneTable[] = {
+       {"GMT", 0,      HOUR(0) },      /* Greenwich Mean */
+       {"BST", 60*60,  HOUR(0) },      /* British Summer */
+       {"WAT", 0,      HOUR(1) },      /* West Africa */
+       {"AT", 0,       HOUR(2) },      /* Azores */
+       {"BST", 0,      HOUR(3) },      /* Brazil Standard */
+       {"NFT", 0,      HOUR(3.5) },    /* Newfoundland */
+       {"NDT", 60*60,  HOUR(3.5) },    /* Newfoundland Daylight */
+       {"AST", 0,      HOUR(4) },      /* Atlantic Standard */
+       {"ADT", 60*60,  HOUR(4) },      /* Atlantic Daylight */
+       {"EST", 0,      HOUR(5) },      /* Eastern Standard */
+       {"EDT", 60*60,  HOUR(5) },      /* Eastern Daylight */
+       {"CST", 0,      HOUR(6) },      /* Central Standard */
+       {"CDT", 60*60,  HOUR(6) },      /* Central Daylight */
+       {"MST", 0,      HOUR(7) },      /* Mountain Standard */
+       {"MDT", 60*60,  HOUR(7) },      /* Mountain Daylight */
+       {"PST", 0,      HOUR(8) },      /* Pacific Standard */
+       {"PDT", 60*60,  HOUR(8) },      /* Pacific Daylight */
+       {"YST", 0,      HOUR(9) },      /* Yukon Standard */
+       {"YDT", 60*60,  HOUR(9) },      /* Yukon Daylight */
+       {"HST", 0,      HOUR(10) },     /* Hawaii Standard */
+       {"HDT", 60*60,  HOUR(10) },     /* Hawaii Daylight */
+       {"NT", 0,       HOUR(11) },     /* Nome */
+       {"IDLW", 0,     HOUR(12) },     /* International Date Line West */
+       {"MET", 0,      -HOUR(1) },     /* Middle European */
+       {"MDT", 60*60,  -HOUR(1) },     /* Middle European Summer */
+       {"EET", 0,      -HOUR(2) },     /* Eastern Europe, USSR Zone 1 */
+       {"BT", 0,       -HOUR(3) },     /* Baghdad, USSR Zone 2 */
+       {"IT", 0,       -HOUR(3.5) },   /* Iran */
+       {"ZP4", 0,      -HOUR(4) },     /* USSR Zone 3 */
+       {"ZP5", 0,      -HOUR(5) },     /* USSR Zone 4 */
+       {"IST", 0,      -HOUR(5.5) },   /* Indian Standard */
+       {"ZP6", 0,      -HOUR(6) },     /* USSR Zone 5 */
+       {"NST", 0,      -HOUR(6.5) },   /* North Sumatra */
+       {"SST", 0,      -HOUR(7) },     /* South Sumatra, USSR Zone 6 */
+       {"WAST", 0,     -HOUR(7) },     /* West Australian Standard */
+       {"WADT", 60*60, -HOUR(7) },     /* West Australian Daylight */
+       {"JT", 0,       -HOUR(7.5) },   /* Java (3pm in Cronusland!) */
+       {"CCT", 0,      -HOUR(8) },     /* China Coast, USSR Zone 7 */
+       {"JST", 0,      -HOUR(9) },     /* Japan Standard, USSR Zone 8 */
+       {"CAST", 0,     -HOUR(9.5) },   /* Central Australian Standard */
+       {"CADT", 60*60, -HOUR(9.5) },   /* Central Australian Daylight */
+       {"EAST", 0,     -HOUR(10) },    /* Eastern Australian Standard */
+       {"EADT", 60*60, -HOUR(10) },    /* Eastern Australian Daylight */
+       {"NZT", 0,      -HOUR(12) },    /* New Zealand */
+       {"NZDT", 60*60, -HOUR(12) },    /* New Zealand Daylight */
+       {  NULL, 0, 0  }
+};
+
+/*
+ * The function ZoneFromTable() searches the table for the current
+ * timezone.  It saves the last one found in ntstr or dststr, depending on
+ * wheter the name is for daylight-saving-time or not.
+ * Both ntstr and dststr are TZ_LEN + 1 chars.
+ */
+static void
+ZoneFromTable(long timezone)
+{
+       register TABLE *tptr = TimezoneTable;
+
+       while (tptr->tz_name != NULL) {
+               if (tptr->zoneoffset == timezone) {
+                       if (tptr->daylight == 0) {
+                               strncpy(ntstr,tptr->tz_name, TZ_LEN);
+                               ntstr[TZ_LEN] = '\0';
+                       } else {
+                               strncpy(dststr,tptr->tz_name, TZ_LEN);
+                               dststr[TZ_LEN] = '\0';
+                       }
+               }
+               tptr++;
+       }
+}
+#endif /* USE_TABLE */
+
 static const char *
 parseZoneName(register char *buf, register const char *p)
 {
@@ -233,6 +323,9 @@ parseTZ(const char *p)
 
        if (!p) return;
 
+#if    USE_TABLE
+       usetable = 0;
+#endif
        if (*p == ':') {
                /*
                 * According to POSIX, this is implementation defined.
@@ -294,7 +387,7 @@ _tzset(void)
 
        _gettimeofday(&tv, &tz);
        _daylight = tz.tz_dsttime;
-       _timezone = tz.tz_minuteswest * 60;
+       _timezone = tz.tz_minuteswest * 60L;
 
 #elif  !defined(_POSIX_SOURCE) && !defined(__USG)
 
@@ -357,11 +450,16 @@ date_of(register struct dsttype *dst, struct tm *timep)
        return day;
 }
 
+/*
+ * The default dst transitions are those for Western Europe (except Great
+ * Britain). 
+ */
 unsigned
 _dstget(register struct tm *timep)
 {
        int begindst, enddst;
        register struct dsttype *dsts = &dststart, *dste = &dstend;
+       int do_dst = 0;
 
        if (_daylight == -1)
                _tzset();
@@ -379,13 +477,14 @@ _dstget(register struct tm *timep)
        /* assume begindst != enddst (otherwise it would be no use) */
        if (begindst < enddst) {                /* northern hemisphere */
                if (timep->tm_yday > begindst && timep->tm_yday < enddst)
-                       return _dst_off;
+                       do_dst = 1;
        } else {                                /* southern hemisphere */
                if (timep->tm_yday > begindst || timep->tm_yday < enddst)
-                       return _dst_off;
+                       do_dst = 1;
        }
 
-       if (timep->tm_yday == begindst || timep->tm_yday == enddst) {
+       if (!do_dst
+           && (timep->tm_yday == begindst || timep->tm_yday == enddst)) {
                long dsttranssec;       /* transition when day is this old */
                long cursec;
 
@@ -397,9 +496,12 @@ _dstget(register struct tm *timep)
 
                if ((timep->tm_yday == begindst && cursec >= dsttranssec)
                    || (timep->tm_yday == enddst && cursec < dsttranssec))
-                       return _dst_off;
+                       do_dst = 1;
        }
+#if USE_TABLE
+       if (usetable) ZoneFromTable(_timezone);
+#endif
+       if (do_dst) return _dst_off;
        timep->tm_isdst = 0;
-
        return 0;
 }