proposed time zone package changes (Hawaii, stack overflow, et al.)
Arthur David Olson
olsona at lecserver.nci.nih.gov
Wed Jan 12 16:24:53 UTC 2011
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>
More information about the tz
mailing list