Below find proposed changes to the time zone package. None of these changes affect current time stamps. The executive summary: * Theory Add section on scope of the database. * australasia Simplification and gratuitous optimization of South Australia rules. * localtime.c In the function tzload, if ALL_STATE is defined, use allocated memory for a large structure rather than using the stack (based on changes suggested by Ted Unangst). * northamerica Changes to Hawaiian time history (from an article by Schmitt and Cox): abandoned local mean time in 1986 rather than 1900; used DST during World War II. * tz-art.htm Add DST joke from first episode of "Conan." * tz-link.htm Align instructions with those in "README" (as suggested by Gilles Espinasse). If no problems are found, these changes will appear in tzcode2011a.tar.gz and tzdata2011.tar.gz on 2011-11-23. --ado diff -r -c old/Theory new/Theory *** old/Theory Tue Oct 12 12:36:50 2010 --- new/Theory Wed Jan 12 10:36:11 2011 *************** *** 1,4 **** ! @(#)Theory 8.5 This file is in the public domain, so clarified as of 2009-05-17 by Arthur David Olson. --- 1,4 ---- ! @(#)Theory 8.6 This file is in the public domain, so clarified as of 2009-05-17 by Arthur David Olson. *************** *** 5,11 **** ----- Outline ----- Time and date functions ! Names of time zone regions Time zone abbreviations Calendrical issues Time and time zones on Mars --- 5,12 ---- ----- Outline ----- Time and date functions ! Scope of the tz database ! Names of time zone rule files Time zone abbreviations Calendrical issues Time and time zones on Mars *************** *** 192,197 **** --- 193,223 ---- better. + ----- Scope of the tz database ----- + + The tz database attempts to record the history and predicted future of + all computer-based clocks that track civil time. To represent this + data, the world is partitioned into regions whose clocks all agree + about time stamps that occur after the somewhat-arbitrary cutoff point + of the POSIX Epoch (1970-01-01 00:00:00 UTC). For each such region, + the database records all known clock transitions, and labels the region + with a notable location. + + Clock transitions before 1970 are recorded for each such location, + because most POSIX-compatible systems support negative time stamps and + could misbehave if data were omitted for pre-1970 transitions. + However, the database is not designed for and does not suffice for + applications requiring accurate handling of all past times everywhere, + as it would take far too much effort and guesswork to record all + details of pre-1970 civil timekeeping. + + As noted in the README file, the tz database is not authoritative + (particularly not for pre-1970 time stamps), and it surely has errors. + Corrections are welcome and encouraged. Users requiring authoritative + data should consult national standards bodies and the references cited + in the database's comments. + + ----- Names of time zone rule files ----- The time zone rule file naming conventions attempt to strike a balance diff -r -c old/australasia new/australasia *** old/australasia Mon Nov 1 09:18:22 2010 --- new/australasia Wed Jan 12 11:03:44 2011 *************** *** 1,5 **** # <pre> ! # @(#)australasia 8.20 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. --- 1,5 ---- # <pre> ! # @(#)australasia 8.22 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. *************** *** 84,97 **** Rule AS 1987 2007 - Oct lastSun 2:00s 1:00 - Rule AS 1972 only - Feb 27 2:00s 0 - Rule AS 1973 1985 - Mar Sun>=1 2:00s 0 - ! Rule AS 1986 1989 - Mar Sun>=15 2:00s 0 - ! Rule AS 1990 only - Mar Sun>=18 2:00s 0 - ! Rule AS 1991 only - Mar Sun>=1 2:00s 0 - ! Rule AS 1992 only - Mar Sun>=18 2:00s 0 - ! Rule AS 1993 only - Mar Sun>=1 2:00s 0 - ! Rule AS 1994 only - Mar Sun>=18 2:00s 0 - Rule AS 1995 2005 - Mar lastSun 2:00s 0 - ! Rule AS 2006 only - Apr Sun>=1 2:00s 0 - Rule AS 2007 only - Mar lastSun 2:00s 0 - Rule AS 2008 max - Apr Sun>=1 2:00s 0 - Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 - --- 84,96 ---- Rule AS 1987 2007 - Oct lastSun 2:00s 1:00 - Rule AS 1972 only - Feb 27 2:00s 0 - Rule AS 1973 1985 - Mar Sun>=1 2:00s 0 - ! Rule AS 1986 1990 - Mar Sun>=15 2:00s 0 - ! Rule AS 1991 only - Mar 3 2:00s 0 - ! Rule AS 1992 only - Mar 22 2:00s 0 - ! Rule AS 1993 only - Mar 7 2:00s 0 - ! Rule AS 1994 only - Mar 20 2:00s 0 - Rule AS 1995 2005 - Mar lastSun 2:00s 0 - ! Rule AS 2006 only - Apr 2 2:00s 0 - Rule AS 2007 only - Mar lastSun 2:00s 0 - Rule AS 2008 max - Apr Sun>=1 2:00s 0 - Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 - diff -r -c old/localtime.c new/localtime.c *** old/localtime.c Tue Oct 12 12:36:51 2010 --- new/localtime.c Thu Dec 16 12:25:20 2010 *************** *** 5,11 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.15"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 5,11 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 8.16"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 337,352 **** register int fid; register int stored; register int nread; ! union { struct tzhead tzhead; char buf[2 * sizeof(struct tzhead) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; ! } u; sp->goback = sp->goahead = FALSE; if (name == NULL && (name = TZDEFAULT) == NULL) ! return -1; { register int doaccess; /* --- 337,362 ---- register int fid; register int stored; register int nread; ! typedef union { struct tzhead tzhead; char buf[2 * sizeof(struct tzhead) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; ! } u_t; ! #ifdef ALL_STATE ! register u_t * up; + up = (u_t *) calloc(1, sizeof *up); + if (up == NULL) + return -1; + #else /* !defined ALL_STATE */ + u_t u; + register u_t * const up = &u; + #endif /* !defined ALL_STATE */ + sp->goback = sp->goahead = FALSE; if (name == NULL && (name = TZDEFAULT) == NULL) ! goto oops; { register int doaccess; /* *************** *** 363,371 **** doaccess = name[0] == '/'; if (!doaccess) { if ((p = TZDIR) == NULL) ! return -1; if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) ! return -1; (void) strcpy(fullname, p); (void) strcat(fullname, "/"); (void) strcat(fullname, name); --- 373,381 ---- doaccess = name[0] == '/'; if (!doaccess) { if ((p = TZDIR) == NULL) ! goto oops; if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) ! goto oops; (void) strcpy(fullname, p); (void) strcat(fullname, "/"); (void) strcat(fullname, name); *************** *** 377,400 **** name = fullname; } if (doaccess && access(name, R_OK) != 0) ! return -1; if ((fid = open(name, OPEN_MODE)) == -1) ! return -1; } ! nread = read(fid, u.buf, sizeof u.buf); if (close(fid) < 0 || nread <= 0) ! return -1; for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; ! ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); ! ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); ! sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); ! sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); ! sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); ! sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); ! p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || --- 387,410 ---- name = fullname; } if (doaccess && access(name, R_OK) != 0) ! goto oops; if ((fid = open(name, OPEN_MODE)) == -1) ! goto oops; } ! nread = read(fid, up->buf, sizeof up->buf); if (close(fid) < 0 || nread <= 0) ! goto oops; for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; ! ttisstdcnt = (int) detzcode(up->tzhead.tzh_ttisstdcnt); ! ttisgmtcnt = (int) detzcode(up->tzhead.tzh_ttisgmtcnt); ! sp->leapcnt = (int) detzcode(up->tzhead.tzh_leapcnt); ! sp->timecnt = (int) detzcode(up->tzhead.tzh_timecnt); ! sp->typecnt = (int) detzcode(up->tzhead.tzh_typecnt); ! sp->charcnt = (int) detzcode(up->tzhead.tzh_charcnt); ! p = up->tzhead.tzh_charcnt + sizeof up->tzhead.tzh_charcnt; if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || *************** *** 401,408 **** sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) ! return -1; ! if (nread - (p - u.buf) < sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ sp->typecnt * 6 + /* ttinfos */ --- 411,418 ---- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) ! goto oops; ! if (nread - (p - up->buf) < sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ sp->typecnt * 6 + /* ttinfos */ *************** *** 410,416 **** sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ ! return -1; for (i = 0; i < sp->timecnt; ++i) { sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p); --- 420,426 ---- sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ ! goto oops; for (i = 0; i < sp->timecnt; ++i) { sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p); *************** *** 419,425 **** for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; if (sp->types[i] >= sp->typecnt) ! return -1; } for (i = 0; i < sp->typecnt; ++i) { register struct ttinfo * ttisp; --- 429,435 ---- for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; if (sp->types[i] >= sp->typecnt) ! goto oops; } for (i = 0; i < sp->typecnt; ++i) { register struct ttinfo * ttisp; *************** *** 429,439 **** p += 4; ttisp->tt_isdst = (unsigned char) *p++; if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) ! return -1; ttisp->tt_abbrind = (unsigned char) *p++; if (ttisp->tt_abbrind < 0 || ttisp->tt_abbrind > sp->charcnt) ! return -1; } for (i = 0; i < sp->charcnt; ++i) sp->chars[i] = *p++; --- 439,449 ---- p += 4; ttisp->tt_isdst = (unsigned char) *p++; if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) ! goto oops; ttisp->tt_abbrind = (unsigned char) *p++; if (ttisp->tt_abbrind < 0 || ttisp->tt_abbrind > sp->charcnt) ! goto oops; } for (i = 0; i < sp->charcnt; ++i) sp->chars[i] = *p++; *************** *** 458,464 **** ttisp->tt_ttisstd = *p++; if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE) ! return -1; } } for (i = 0; i < sp->typecnt; ++i) { --- 468,474 ---- ttisp->tt_ttisstd = *p++; if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE) ! goto oops; } } for (i = 0; i < sp->typecnt; ++i) { *************** *** 471,477 **** ttisp->tt_ttisgmt = *p++; if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE) ! return -1; } } /* --- 481,487 ---- ttisp->tt_ttisgmt = *p++; if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE) ! goto oops; } } /* *************** *** 504,514 **** /* ** If this is an old file, we're done. */ ! if (u.tzhead.tzh_version[0] == '\0') break; ! nread -= p - u.buf; for (i = 0; i < nread; ++i) ! u.buf[i] = p[i]; /* ** If this is a narrow integer time_t system, we're done. */ --- 514,524 ---- /* ** If this is an old file, we're done. */ ! if (up->tzhead.tzh_version[0] == '\0') break; ! nread -= p - up->buf; for (i = 0; i < nread; ++i) ! up->buf[i] = p[i]; /* ** If this is a narrow integer time_t system, we're done. */ *************** *** 516,528 **** break; } if (doextend && nread > 2 && ! u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES) { struct state ts; register int result; ! u.buf[nread - 1] = '\0'; ! result = tzparse(&u.buf[1], &ts, FALSE); if (result == 0 && ts.typecnt == 2 && sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { for (i = 0; i < 2; ++i) --- 526,538 ---- break; } if (doextend && nread > 2 && ! up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES) { struct state ts; register int result; ! up->buf[nread - 1] = '\0'; ! result = tzparse(&up->buf[1], &ts, FALSE); if (result == 0 && ts.typecnt == 2 && sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { for (i = 0; i < 2; ++i) *************** *** 566,572 **** --- 576,590 ---- break; } } + #ifdef ALL_STATE + (void) free((void *) up); + #endif /* defined ALL_STATE */ return 0; + oops: + #ifdef ALL_STATE + (void) free((void *) up); + #endif /* defined ALL_STATE */ + return -1; } static int diff -r -c old/northamerica new/northamerica *** old/northamerica Mon Nov 1 09:18:22 2010 --- new/northamerica Thu Dec 16 16:58:32 2010 *************** *** 1,5 **** # <pre> ! # @(#)northamerica 8.34 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. --- 1,5 ---- # <pre> ! # @(#)northamerica 8.36 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. *************** *** 471,490 **** # three votes for and one against." # Hawaii ! # ! # From Arthur David Olson: ! # And then there's Hawaii. ! # DST was observed for one day in 1933; ! # standard time was changed by half an hour in 1947; ! # it's always standard as of 1986. ! # ! # From Paul Eggert: ! # Shanks says the 1933 experiment lasted for three weeks. Go with Shanks. ! # ! Zone Pacific/Honolulu -10:31:26 - LMT 1900 Jan 1 12:00 ! -10:30 - HST 1933 Apr 30 2:00 -10:30 1:00 HDT 1933 May 21 2:00 ! -10:30 US H%sT 1947 Jun 8 2:00 -10:00 - HST # Now we turn to US areas that have diverged from the consensus since 1970. --- 471,504 ---- # three votes for and one against." # Hawaii ! ! # From Arthur David Olson (2010-12-09): ! # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225 ! # of volume 26 of The Hawaian Journal of History (1992). As of 2010-12-09, ! # the article is available at ! # <a href="http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/jl26215.pdf"> ! # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/jl26215.pdf ! # </a> ! # and indicates that standard time was adopted effective noon, January ! # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight ! # saving for the period between the last Sunday of each April and the ! # last Sunday of each September, but less than a month later repealed the ! # act," (page 220), that year-round daylight saving time was in effect ! # from 1942-02-09 to 1945-09-30 (page 221, with no time of day given for ! # when clocks changed) and that clocks were changed by 30 minutes ! # effective the second Sunday of June, 1947 (page 219, with no time of ! # day given for when clocks changed). A footnote for the 1933 changes ! # cites Session Laws of Hawaii 1933, "Act. 90 (approved 26 Apr. 1933) ! # and Act 163 (approved 21 May 1933)." Unless the Act was approved very ! # early on the 21st, the time for transition out of DST in 1933 below ! # is wrong. ! ! Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00 #Schmitt&Cox ! -10:30 - HST 1933 Apr 30 2:00 #Schmitt&Cox+2 -10:30 1:00 HDT 1933 May 21 2:00 ! -10:30 1:00 HST 1942 Feb 09 2:00 #Schmitt&Cox+2 ! -10:30 - HDT 1945 Sep 30 2:00 #Schmitt&Fox+2 ! -10:30 US H%sT 1947 Jun 8 2:00 #Schmitt&Fox+2 -10:00 - HST # Now we turn to US areas that have diverged from the consensus since 1970. diff -r -c old/tz-art.htm new/tz-art.htm *** old/tz-art.htm Tue Oct 12 12:36:52 2010 --- new/tz-art.htm Wed Jan 12 10:56:44 2011 *************** *** 9,15 **** <body> <h1>Time and the Arts</h1> <address> ! @(#)tz-art.htm 8.17 </address> <p> This file is in the public domain, so clarified as of --- 9,15 ---- <body> <h1>Time and the Arts</h1> <address> ! @(#)tz-art.htm 8.18 </address> <p> This file is in the public domain, so clarified as of *************** *** 467,472 **** --- 467,479 ---- It is already tomorrow in Australia." (Charles M. Schulz, provided by Steve Summit) </li> + <li> + "I put myself and my staff through this crazy, huge ordeal, all because + I refused to go on at midnight, okay? And so I work, you know, and + then I get this job at eleven, supposed to be a big deal. Then + yesterday daylight [saving] time ended. Right now it's basically + midnight." (Conan O'Brien on the 2010-11-08 premier of "Conan.") + </li> </ul> </body> </html> diff -r -c old/tz-link.htm new/tz-link.htm *** old/tz-link.htm Tue Oct 12 12:36:52 2010 --- new/tz-link.htm Wed Jan 12 10:40:27 2011 *************** *** 18,24 **** <body> <h1>Sources for Time Zone and Daylight Saving Time Data</h1> <address> ! @(#)tz-link.htm 8.30 </address> <p> This file is in the public domain, so clarified as of --- 18,24 ---- <body> <h1>Sources for Time Zone and Daylight Saving Time Data</h1> <address> ! @(#)tz-link.htm 8.31 </address> <p> This file is in the public domain, so clarified as of *************** *** 96,102 **** these files to a <abbr>GNU</abbr>/Linux or similar host; see the downloaded <code>README</code> file for what to do next.</p> ! <pre style="margin-left: 2em"><code><a href="http://www.gnu.org/software/wget/">wget</a> 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz' <a href="http://www.gnu.org/software/gzip/">gzip</a> -dc tzcode*.tar.gz | <a href="http://www.gnu.org/software/tar/">tar</a> -xf - gzip -dc tzdata*.tar.gz | tar -xf - </code></pre> --- 96,104 ---- these files to a <abbr>GNU</abbr>/Linux or similar host; see the downloaded <code>README</code> file for what to do next.</p> ! <pre style="margin-left: 2em"><code>mkdir tz ! cd tz ! <a href="http://www.gnu.org/software/wget/">wget</a> 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz' <a href="http://www.gnu.org/software/gzip/">gzip</a> -dc tzcode*.tar.gz | <a href="http://www.gnu.org/software/tar/">tar</a> -xf - gzip -dc tzdata*.tar.gz | tar -xf - </code></pre>