tz
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1999 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1998 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1997 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1996 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1995 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1994 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1993 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1992 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1991 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1990 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1989 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1988 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1987 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1986 -----
- December
- November
- 9 participants
- 7523 discussions
Andy Lipscomb has been added to the time zone mailing list; this message
predates the addition.
--ado
-----Original Message-----
From: Andy Lipscomb [mailto:AndyLipscomb@decosimo.com]
Sent: Friday, January 20, 2006 12:39 PM
To: tz(a)lecserver.nci.nih.gov
Cc: ewwa(a)chattanooga.net
Subject: Indiana time zones
Actually, there are seven other counties that are moving from Eastern to
Central time. Since they, like Starke County, do so at the time change,
they will simply skip the spring-forward--2:00 EST and 2:00 CDT are
identical (both equal 21:00 UTC on the previous day). It appears to me
that this requires creating a new zone for the other seven counties,
which I show below.
# From J. Andrew Lipscomb (2006-01-20):
# Department of Transportation ruling
http://www.dot.gov/affairs/dot0406.htm
# adds eight new counties to the Central (America/Chicago) zone. Six are
in # the Evansville area, two near Chicago. One of them (Starke) already
has its # own entry; as for the other seven, the largest city in them
(and an old # territorial capital) is Vincennes. I suggest that for the
exemplar city of # the seven counties.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Vincennes -5:50:04 - LMT 1883 Nov 18 12:09:56
-6:00 US C%sT 1920
-6:00 Indianapolis C%sT 1942
-6:00 US C%sT 1946
-6:00 Indianapolis C%sT 1955 Apr 24 2:00
-5:00 - EST 1957 Sep 29 2:00
-6:00 - CST 1958 Apr 27 2:00
-5:00 - EST 1969
-5:00 US E%sT 1971
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
In addition to the section above, the new zone will need to be added to
the zone.tab file. Vincennes' location is
+384042-0873058.
And to cover Starke County:
# From J. Andrew Lipscomb (2006-01-20):
# The Department of Transportation placed Starke County back on Central
time, # beginning at the 2006 DST start.
# Rule NAME FROM TO TYPE IN ON AT SAVE
LETTER
Rule Starke 1947 1961 - Apr lastSun 2:00 1:00
D
Rule Starke 1947 1954 - Sep lastSun 2:00 0
S
Rule Starke 1955 1956 - Oct lastSun 2:00 0
S
Rule Starke 1957 1958 - Sep lastSun 2:00 0
S
Rule Starke 1959 1961 - Oct lastSun 2:00 0
S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
-6:00 US C%sT 1947
-6:00 Starke C%sT 1962 Apr 29 2:00
-5:00 - EST 1963 Oct 27 2:00
-6:00 US C%sT 1991 Oct 27 2:00
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
2
1
Jan. 22, 2006
> I vaguely recall that it's because zic recognizes this situation
> specially, and refuses to create the two hour-apart transitions that
> the rules would require if applied strictly. Instead, it merges the
> transitions in the common-sense way.
A hunt in the archives shows that Paul's vague recollection is correct.
Historically there have been places that went through the same transition
that's about to happen in Knox; these places have done it without
changing their wall clocks. Zic is set up to recognize the situation and
"do the right thing;" given DOT's docket, the right way may not be DOT's way.
For those on deadlines: to get DOT-mandated behavior,
one ugly possibility is to lie by a second:
instead of having a Zone such as...
Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
...
-5:00 - EST 2006 Apr 2 2
-6:00 US C%sT
...you'd have a zone such as...
Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
...
-5:00 - EST 2006 Apr 2 1:59:59
-6:00 US C%sT
Matters at hand are to reconsider zic's change-collapsing behavior,
document the change-collapsing behavior if it's kept,
and--if DOT-mandated behavior is desired--figure out the best way to
get that behavior out of the change-collapsing zics already out in the field.
Below find excerpts from three relevant messages from 1996.
--ado
===============================================================================
> From eggert(a)twinsun.com Wed May 1 18:40:19 1996
> Return-Path: <eggert(a)twinsun.com>
> Received: from alcor.twinsun.com by elsie.nci.nih.gov (4.1/SMI-4.1)
> id AA26147; Wed, 1 May 96 18:40:19 EDT
> Received: from der.twinsun.com (der.twinsun.com [192.54.239.42]) by alcor.twinsun.com (8.6.12/8.6.5) with ESMTP id PAA02100 for <tz(a)elsie.nci.nih.gov>; Wed, 1 May 1996 15:35:54 -0700
> Received: from bird.twinsun.com by der.twinsun.com (SMI-8.6/SMI-SVR4)
> id PAA17702; Wed, 1 May 1996 15:40:05 -0700
> Received: by bird.twinsun.com (SMI-8.6/SMI-SVR4)
> id PAA11877; Wed, 1 May 1996 15:40:04 -0700
> Date: Wed, 1 May 1996 15:40:04 -0700
> Message-Id: <199605012240.PAA11877(a)bird.twinsun.com>
> From: Paul Eggert <eggert(a)twinsun.com>
> To: tz(a)elsie.nci.nih.gov
> Subject: bug in zic for Rule and Zone changing simultaneously?
> Status: RO
>
> I found 23 bugs in the latest tz database. I enclose two detailed
> examples below, and a brief summary of all the bugs. It appears that
> zic has problems when applying Zone and Rule changes simultaneously.
>
>
> Example 1. The edited input is:
>
> # Rule NAME FROM TO TYPE IN ON AT SAVE LET
> Rule Falk 1985 max - Sep Sun>=9 0:00 1:00 D
> # Zone NAME GMTOFF RULES FORMAT [UNTIL]
> Zone Atlantic/Stanley -3:00 Falk E%sT 1985 Sep 15
> -4:00 Falk A%sT
>
> The zdump -v output is:
>
> Atlantic/Stanley Sun Sep 15 02:59:59 1985 GMT = Sat Sep 14 23:59:59 1985 EST isdst=0
> Atlantic/Stanley Sun Sep 15 03:00:00 1985 GMT = Sat Sep 14 23:00:00 1985 AST isdst=0
> Atlantic/Stanley Sun Sep 15 03:59:59 1985 GMT = Sat Sep 14 23:59:59 1985 AST isdst=0
> Atlantic/Stanley Sun Sep 15 04:00:00 1985 GMT = Sun Sep 15 01:00:00 1985 ADT isdst=1
>
> zdump claims that inhabitants of Stanley changed their clocks twice
> that night, when they changed them only once. The transition should
> have been from
> 1985-09-14 23:59:59 -0300 (EST) to
> 1985-09-15 00:00:00 -0400 (ADT), but zic applied `Zone' first, yielding
> 1985-09-14 23:00:00 -0200 (EDT), and then one hour later applied `Rule',
> yielding the proper time afterwards; but there's a one-hour period of
> incorrect times.
>
>
> Example 2. The input is:
>
> # Rule NAME FROM TO TYPE IN ON AT SAVE LET
> Rule Regina 1905 only - Sep 1 0:00 0 S
> # Zone NAME GMTOFF RULES FORMAT [UNTIL]
> Zone America/Regina -6:58:36 - LMT 1905 Sep
> -7:00 Regina M%sT 1966 Apr 15
>
> The zdump output is:
>
> America/Regina Fri Sep 1 06:58:35 1905 GMT = Thu Aug 31 23:59:59 1905 LMT isdst=0
> America/Regina Fri Sep 1 06:58:36 1905 GMT = Thu Aug 31 23:58:36 1905 LMT isdst=0
> America/Regina Fri Sep 1 06:59:59 1905 GMT = Thu Aug 31 23:59:59 1905 LMT isdst=0
> America/Regina Fri Sep 1 07:00:00 1905 GMT = Fri Sep 1 00:00:00 1905 MST isdst=0
>
> Again, there are two transitions where there should be one, and it's
> because the Zone was applied before the Rule, when they were meant to
> be applied simultaneously. In this case, the erroneous period is only
> 84 seconds long.
>
>
> Here is a list of the 23 bugs I found. Each line has the following
> columns:
>
> timezone name
> first time_t value in the erroneous period (1)
> first time_t value after the erroneous period is over (2)
> ctime applied to (1)
> ctime applied to (2)
>
> America/Asuncion 134017200 134020800 Sun Mar 31 23:00:00 1974 Mon Apr 1 00:00:00 1974
> America/Barbados -1199217720 -1199217600 Thu Dec 31 23:58:00 1931 Fri Jan 1 00:00:00 1932
> America/Belize -1822500432 -1822500000 Sun Mar 31 23:52:48 1912 Mon Apr 1 00:00:00 1912
> America/Costa_Rica -1545071040 -1545069600 Fri Jan 14 23:36:00 1921 Sat Jan 15 00:00:00 1921
> America/El_Salvador -1546279392 -1546279200 Fri Dec 31 23:56:48 1920 Sat Jan 1 00:00:00 1921
> America/Juneau 436352400 436356000 Sun Oct 30 01:00:00 1983 Sun Oct 30 01:00:00 1983
> ...
===============================================================================
> From ado Tue May 14 14:31:50 1996
> Return-Path: <ado>
> Received: by elsie.nci.nih.gov (4.1/SMI-4.1)
> id AA07673; Tue, 14 May 96 14:31:50 EDT
> Date: Tue, 14 May 96 14:31:50 EDT
> From: ado (Arthur David Olson)
> Message-Id: <9605141831.AA07673(a)elsie.nci.nih.gov>
> To: tz
> Subject: Simultaneous zone and DST changes
> Status: RO
>
> The basic challenge with places such as Stanley (where a time-zone shift and
> a DST change were done at the same instant in 1985, resulting in no change of
> wall clock time) is that there's an hour when such a place is neither fish nor
> fowl. Here's a table summarizing what's happening on September 14/15 1995
> in five different circumstances; each row of the table gives data for a
> particular instant in time. The circumstances:
> 1. What's happening in places that run on GMT
> 2. What's happening in (hypothetical) places that always run on EST/EDT
> using Falkland rules
> 3. What's happening in (hypothetical) places that always run on AST/ADT
> using Falkland rules
> 4. What zdump tells us is currently produced by zic for Stanley
> 5. And what we (presumably) really want for Stanley.
> ===============================================================================
> GMT-------|Always-ExT-----|Always-AxT-----|Stanley (now)--|Stanley (wanted)
> 15 2:59:59|14 23:59:59 EST|14 22:59:59 AST|14 23:59:59 EST|14 23:59:59 EST
> 15 3:00:00|15 01:00:00 EDT|14 23:00:00 AST|14 23:00:00 AST|15 00:00:00 ADT/EST
> 15 3:59:59|15 01:59:59 EDT|14 23:59:59 AST|14 23:59:59 AST|15 00:59:59 ADT/EST
> 15 4:00:00|15 02:00:00 EDT|15 01:00:00 ADT|15 01:00:00 ADT|15 01:00:00 ADT
> ===============================================================================
> The "Stanley (wanted)" stuff matches neither the "Always ExT" stuff nor the
> "Always AxT" stuff (regardless of whether you pick ADT or EST for Stanley to
> use as a time zone abbreviation during the strange hour).
>
> Among the ways to get from "Stanley (now)" to "Stanley (wanted)":
>
> 1. Hard code the transition hour--that is, where there are now lines that read...
>
> Zone Atlantic/Stanley -3:51:24 - LMT 1890
> -3:51 - SMT 1912 Mar 12
> -4:00 Falk A%sT 1983 May
> -3:00 Falk E%sT 1985 Sep 15
> -4:00 Falk A%sT
>
> ...add a line to cover the hour in 1985...
>
> Zone Atlantic/Stanley -3:51:24 - LMT 1890
> -3:51 - SMT 1912 Mar 12
> -4:00 Falk A%sT 1983 May
> -3:00 Falk E%sT 1985 Sep 15
> -3:00 - EST 1985 Sep 15 1:00 # <<<<
> -4:00 Falk A%sT
>
> 2. Set up zic to notice situations such as the above and "do the right thing."
> This would involve a code change something like this (with the "horrid
> special case" check perhaps made more strict):
> ===============================================================================
> ...
> ===============================================================================
> I lean toward the second approach; are there any better ideas out there?
>
> --ado
===============================================================================
> From eggert(a)twinsun.com Wed May 15 03:55:30 1996
> Return-Path: <eggert(a)twinsun.com>
> Received: from alcor.twinsun.com by elsie.nci.nih.gov (4.1/SMI-4.1)
> id AA10516; Wed, 15 May 96 03:55:30 EDT
> Received: from der.twinsun.com (der.twinsun.com [192.54.239.42]) by alcor.twinsun.com (8.6.12/8.6.5) with ESMTP id AAA03404; Wed, 15 May 1996 00:49:16 -0700
> Received: from bird.twinsun.com by der.twinsun.com (SMI-8.6/SMI-SVR4)
> id AAA19194; Wed, 15 May 1996 00:55:12 -0700
> Received: by bird.twinsun.com (SMI-8.6/SMI-SVR4)
> id AAA01768; Wed, 15 May 1996 00:55:11 -0700
> Date: Wed, 15 May 1996 00:55:11 -0700
> Message-Id: <199605150755.AAA01768(a)bird.twinsun.com>
> From: Paul Eggert <eggert(a)twinsun.com>
> To: ado(a)elsie.nci.nih.gov
> Cc: tz(a)elsie.nci.nih.gov
> In-Reply-To: <9605141831.AA07673(a)elsie.nci.nih.gov> (ado(a)elsie.nci.nih.gov)
> Subject: Re: Simultaneous zone and DST changes
> Status: RO
>
> Date: Tue, 14 May 96 14:31:50 EDT
> From: ado(a)elsie.nci.nih.gov (Arthur David Olson)
>
> I lean toward the second approach; are there any better ideas out there?
>
> How about the following implementation of the 2nd approach instead?
> It's the same basic idea, except that the two transitions are merged
> if their before-transition localtimes are the same (or if the latter
> precedes the former!). This should avoid the horridness of the 1-hour
> special case.
>
> This patch fixes bugs in the following transitions:
>
> 1919-03-01 Europe/Brussels
> 1973-04-29 America/Menominee
> 1983-10-30 America/Juneau
> 1985-04-19 Asia/Istanbul
> 1985-09-15 Atlantic/Stanley
>
> ===================================================================
> RCS file: RCS/zic.c,v
> retrieving revision 1996.6
> retrieving revision 1996.6.1.2
> diff -c -r1996.6 -r1996.6.1.2
> *** zic.c 1996/05/03 02:49:23 1996.6
> --- zic.c 1996/05/15 07:51:50 1996.6.1.2
> ***************
> *** 1397,1406 ****
> if (isdsts[0] == 0)
> while (attypes[fromi].type == 0)
> ++fromi; /* handled by default rule */
> ! for ( ; fromi < timecnt; ++fromi)
> if (toi == 0 ||
> attypes[toi - 1].type != attypes[fromi].type)
> attypes[toi++] = attypes[fromi];
> timecnt = toi;
> }
> /*
> --- 1397,1416 ----
> if (isdsts[0] == 0)
> while (attypes[fromi].type == 0)
> ++fromi; /* handled by default rule */
> ! for ( ; fromi < timecnt; ++fromi) {
> ! if (toi != 0
> ! && ((attypes[fromi].at
> ! + gmtoffs[attypes[toi - 1].type])
> ! <= (attypes[toi - 1].at
> ! + gmtoffs[toi == 1 ? 0
> ! : attypes[toi - 2].type]))) {
> ! attypes[toi - 1].type = attypes[fromi].type;
> ! continue;
> ! }
> if (toi == 0 ||
> attypes[toi - 1].type != attypes[fromi].type)
> attypes[toi++] = attypes[fromi];
> + }
> timecnt = toi;
> }
> /*
1
0
Judith S. Kaleta
Office of the General Counsel
US Dept. of Transportation
Room 10428
400 Seventh St
Washington, DC 20590
Dear Ms. Kaleta:
I help maintain the public-domain tz database of time zone and
daylight saving time transitions. This database contains code and
data that represent the history of local time, and is used by many
computers around the world. For details, please see
<http://www.twinsun.com/tz/tz-link.htm>. Needless to say, we've been
following the Indiana situation with interest.
Deborah Goldsmith of Apple Computer, one of our correspondents,
recently noted what appears to be a one-hour error in docket
OST-2005-22114 <http://dmses.dot.gov/docimages/pdf95/382329_web.pdf>.
Quoting from the first page of that document:
DATES: The effective date of this rule is 2:00 a.m. EST Sunday,
April 2, 2006, which is the changeover date from standard time to
Daylight Saving Time.
This cannot be exactly what was intended, because 2:00 a.m. EST
corresponds to 1:00 a.m. CST, at which point clocks in the Central
time zone will not spring forward for another hour. Therefore, as
written, the rule requires that a clock in the affected area must jump
backwards from 02:00 EST to 01:00 CST, and then an hour later jump
ahead from 02:00 CST to 03:00 CDT. In other words, the
currently-required clock transitions would look like this:
01:59:59 EST
... and then, one second later,...
01:00:00 CST
...
...
... and then, one hour later,...
01:59:59 CST
... and then, one second later,...
03:00:00 CDT
We doubt whether you really intended that the citizens of Vincennes,
Indiana should stay up in the middle of the night and change their
clocks twice.
Our correspondents have suggested two different ways out of this
problem. First, and perhaps simplest, you could change the effective
time of the rule from 2:00 a.m. EST to 3:00 a.m. EST. This will
result in the following transition:
02:59:59 EST
... and then, one second later,...
03:00:00 CDT
Second, if you prefer sticking to a 2:00 a.m. transition, you could
append the following sentences:
Counties that move from the Eastern to the Central Time Zone will
switch directly from EST to CDT, so that their clocks need not
change. From 2:00 a.m. CDT to 3:00 a.m. CDT these clocks will use
CDT even though the rest of the Central Time Zone will still be
using CST.
This would result in the following transition:
01:59:59 EST
... and then, one second later,...
02:00:00 CDT
Please let us know which solution (if any) you prefer, by writing to
us in the time zone mailing list <tz(a)elsie.nci.nih.gov>. Thanks.
Sincerely,
Paul Eggert
Computer Science Dept.
4532J Boelter Hall
University of California
Los Angeles, CA 90095-1596
+1 310 267 2254 (voice)
eggert(a)ucla.edu (email)
1
0
Jan. 21, 2006
I am inclined to think you should implement the letter of the law rather
than guessing what DOT "really" meant. Either that or ask DOT for
clarification. I hate to say it, but I've been involved in similar things
that became a legal issue and the difference can matter.
Unfortunately, this conflicts with the deadline. Maybe I'm a bit paranoid,
but I'd ask.
++PLS
-----Original Message-----
From: tz-request(a)elsie.nci.nih.gov [mailto:tz-request@elsie.nci.nih.gov] On
Behalf Of Deborah Goldsmith
Sent: Friday, January 20, 2006 7:08 PM
To: tz(a)lecserver.nci.nih.gov
Subject: Re: proposed tz patches for Indiana, New Brunswick, Gaza, etc.
On Jan 20, 2006, at 2:59 PM, Paul Eggert wrote:
> + -5:00 - EST 2006 Apr 2 2:00
> + -6:00 US C%sT
For all the Indiana counties that are switching from ET to CT, shouldn't
this be:
+ -5:00 - EST 2006 Apr 2 2:00
+ -5:00 - CDT 2006 Apr 2 3:00
+ -6:00 US C%sT
so that the time will proceed smoothly from 1:59:59 AM EST to 2:00:00 AM
CDT, as proposed by Paul Eggert?
With the rules the way they are now, the time will go from 1:59:59 AM EST to
1:00:00 AM CST, then from 1:59:59 AM CST to 3:00:00 AM CDT.
Personally, I'm fine either way.
Deborah
2
1
Probably I'm missing something, but why "2:00 AM CST to 1:00 AM CDT". In the
spring, 1:59:59 is followed 1 second later by 3:00:00 CDT. I don't
understand why you have it in the other direction.
++PLS
-----Original Message-----
From: tz-request(a)elsie.nci.nih.gov [mailto:tz-request@elsie.nci.nih.gov] On
Behalf Of Deborah Goldsmith
Sent: Wednesday, January 18, 2006 7:12 PM
To: tz(a)lecserver.nci.nih.gov
Subject: Re: DOT issues final ruling on Indiana time zones
You're right, that should have been "fall back from 2:00 AM EST to 1:00 AM
CST, then again from 2:00 AM CST to 1:00 AM CDT". Sorry about that.
From the final DOT ruling (posted earlier) it appears as though that is in
fact the correct behavior, too, as odd as it is.
Deborah
On Jan 18, 2006, at 5:38 PM, Paul Schauble wrote:
> Since this is in the spring, shouldn't that last change be from 2AM
> CST to 3AM CDT?
>
> ++PLS
>
> -----Original Message-----
> From: tz-request(a)elsie.nci.nih.gov [mailto:tz-
> request(a)elsie.nci.nih.gov] On Behalf Of Deborah Goldsmith
> Sent: Wednesday, January 18, 2006 5:38 PM
> To: tz(a)lecserver.nci.nih.gov
> Subject: DOT issues final ruling on Indiana time zones
>
> <snip>
> assuming I'm interpreting everything correctly. The DOT doesn't
> specify whether Starke county switch to Central Time at the
> appropriate time for its old or new time zone, but I'm assuming the
> old here. That leads to it falling back from 2:00AM EST to 1:00AM CST,
> and then again from 2:00AM CST to 1:00AM CST. If that makes people
> nervous, then the transition would need to be at 3:00 AM.
>
> Deborah Goldsmith
> Internationalization, Unicode liaison
> Apple Computer, Inc.
> goldsmit(a)apple.com
>
6
7
Actually, there are seven other counties that are moving from Eastern to Central time. Since they, like Starke County, do so at the time change, they will simply skip the spring-forward--2:00 EST and 2:00 CDT are identical (both equal 21:00 UTC on the previous day). It appears to me that this requires creating a new zone for the other seven counties, which I show below.
# From J. Andrew Lipscomb (2006-01-20):
# Department of Transportation ruling http://www.dot.gov/affairs/dot0406.htm
# adds eight new counties to the Central (America/Chicago) zone. Six are in
# the Evansville area, two near Chicago. One of them (Starke) already has its
# own entry; as for the other seven, the largest city in them (and an old
# territorial capital) is Vincennes. I suggest that for the exemplar city of
# the seven counties.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Vincennes -5:50:04 - LMT 1883 Nov 18 12:09:56
-6:00 US C%sT 1920
-6:00 Indianapolis C%sT 1942
-6:00 US C%sT 1946
-6:00 Indianapolis C%sT 1955 Apr 24 2:00
-5:00 - EST 1957 Sep 29 2:00
-6:00 - CST 1958 Apr 27 2:00
-5:00 - EST 1969
-5:00 US E%sT 1971
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
In addition to the section above, the new zone will need to be added to the zone.tab file. Vincennes' location is
+384042-0873058.
And to cover Starke County:
# From J. Andrew Lipscomb (2006-01-20):
# The Department of Transportation placed Starke County back on Central time,
# beginning at the 2006 DST start.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Starke 1947 1961 - Apr lastSun 2:00 1:00 D
Rule Starke 1947 1954 - Sep lastSun 2:00 0 S
Rule Starke 1955 1956 - Oct lastSun 2:00 0 S
Rule Starke 1957 1958 - Sep lastSun 2:00 0 S
Rule Starke 1959 1961 - Oct lastSun 2:00 0 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
-6:00 US C%sT 1947
-6:00 Starke C%sT 1962 Apr 29 2:00
-5:00 - EST 1963 Oct 27 2:00
-6:00 US C%sT 1991 Oct 27 2:00
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
1
0
The DOT final ruling on Indiana came out today:
http://www.dot.gov/affairs/dot0406.htm
Based on my reading of this document, only one zone in tzdata is
affected, America/Indiana/Knox. That zone will start observing US
Central Time starting April 2, 2006, at the time of the switchover to
Daylight Savings Time. Probably the easiest thing to do is to change
the last two lines as follows:
From:
-5:00 - EST 2006
-5:00 US E%sT
to:
-5:00 - EST 2006 Apr 2 2:00
-5:00 US C%sT
assuming I'm interpreting everything correctly. The DOT doesn't
specify whether Starke county switch to Central Time at the
appropriate time for its old or new time zone, but I'm assuming the
old here. That leads to it falling back from 2:00AM EST to 1:00AM
CST, and then again from 2:00AM CST to 1:00AM CST. If that makes
people nervous, then the transition would need to be at 3:00 AM.
Deborah Goldsmith
Internationalization, Unicode liaison
Apple Computer, Inc.
goldsmit(a)apple.com
2
2
Here's the latest version of proposed changes to the time zone package to
cope with 64-bit time values. As usual, these are differences from the
stuff that's available at ftp://elsie.nci.nih.gov/pub/tz{code,data}2005r.tar.gz.
I ran the package before and after these changes through the zgress
wringer that I sent out on Tuesday; here on elsie (a 32-bit system)
I get the same results from a zdump of all the binary data files
whether I use the before or after zdump and whether I use the
before or after data files.
For those who missed earlier rounds: the "new" version of zic generates a
three-part binary file; the file starts off with "Tzif2" (rather than the
old "Tzif\0"). The first part (other than the change in the magic "Tzif" string)
is identical in format to the existing time zone binary files. The second part
has the same format except that 64 bits are stored for each time value (rather
than the old 32 bits). The third part is a newline-enclosed POSIX-format
time zone string (such as "EST5EDT,M3.2.0,M11.1.0") if the future of the zone
can be represented with such a string, or a newline-enclosed null string
otherwise.
If a zone's future can't be represented by a POSIX string, the new zic
generates 400 years worth of 64-bit time transition information; the stuff
in "localtime.c" sees if there's 400 years worth of regularity at the end of
the data and, if so, does its work modulo 400 to extend the data into the
very far future.
Given the magnitude of these changes I'll wait a while for feedback;
since these changes have already been around the block a couple of times
and since they pass the regression test, I won't wait too long.
Absent negative feedback, expect the changes to show up in the ftp version
on Presidents' Day (2006-02-20).
The changes below also reflect Roland McGrath's scheck suggestions.
--ado
*** tzftp/tzfile.5 Thu Dec 22 09:31:16 2005
--- tzexp3/tzfile.5 Tue Jan 17 14:42:56 2006
***************
*** 9,15 ****
.IR tzset (3)
begin with the magic characters "TZif" to identify then as
time zone information files,
! followed by sixteen bytes reserved for future use,
followed by six four-byte values of type
.BR long ,
written in a ``standard'' byte order
--- 9,17 ----
.IR tzset (3)
begin with the magic characters "TZif" to identify then as
time zone information files,
! followed by a character identifying the version of the file's format
! (as of 2005, either an ASCII NUL or a '2')
! followed by fifteen bytes containing zeroes reserved for future use,
followed by six four-byte values of type
.BR long ,
written in a ``standard'' byte order
***************
*** 131,138 ****
.I tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
.SH SEE ALSO
newctime(3)
! .\" @(#)tzfile.5 7.12
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
--- 133,150 ----
.I tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
+ .PP
+ For version-2-format time zone files,
+ the above header and data is followed by a second header and data,
+ identical in format except that
+ eight bytes are used for each transition time or leap second time.
+ After the second header and data comes a newline-encloded,
+ POSIX-TZ-environment-variable-style string for use in handling instants
+ after the last transition time stored in the file
+ (with nothing between the newlines if there is no POSIX representation for
+ such instants).
.SH SEE ALSO
newctime(3)
! .\" @(#)tzfile.5 7.13
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
*** tzftp/Makefile Thu Dec 22 09:31:13 2005
--- tzexp3/Makefile Tue Jan 17 14:42:54 2006
***************
*** 1,4 ****
! # @(#)Makefile 7.109
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
--- 1,4 ----
! # @(#)Makefile 7.110
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
***************
*** 95,100 ****
--- 95,101 ----
# -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4)
# -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD)
# -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD)
+ # -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h"
# -DHAVE_STRERROR=0 if your system lacks the strerror function
# -DHAVE_SYMLINK=0 if your system lacks the symlink function
# -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h"
*** tzftp/tzfile.h Thu Dec 22 09:31:16 2005
--- tzexp3/tzfile.h Tue Jan 17 15:05:09 2006
***************
*** 21,27 ****
#ifndef lint
#ifndef NOID
! static char tzfilehid[] = "@(#)tzfile.h 7.18";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 21,27 ----
#ifndef lint
#ifndef NOID
! static char tzfilehid[] = "@(#)tzfile.h 7.19";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 49,55 ****
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
! char tzh_reserved[16]; /* reserved for future use */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
--- 49,56 ----
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
! char tzh_version[1]; /* '\0' or '2' as of 2005 */
! char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
***************
*** 84,101 ****
*/
/*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
! /*
! ** The TZ_MAX_TIMES value below is enough to handle a bit more than a
! ** year's worth of solar time (corrected daily to the nearest second) or
! ** 138 years of Pacific Presidential Election time
! ** (where there are three time zone transitions every fourth year).
! */
! #define TZ_MAX_TIMES 370
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
--- 85,106 ----
*/
/*
+ ** If tzh_version is '2' or greater, the above is followed by a second instance
+ ** of tzhead and a second instance of the data in which each coded transition
+ ** time uses 8 rather than 4 chars,
+ ** then a POSIX-TZ-environment-variable-style string for use in handling
+ ** instants after the last transition time stored in the file
+ ** (with nothing between the newlines if there is no POSIX representation for
+ ** such instants).
+ */
+
+ /*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
! #define TZ_MAX_TIMES 1200
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
*** tzftp/private.h Thu Dec 22 09:31:15 2005
--- tzexp3/private.h Tue Jan 17 15:36:50 2006
***************
*** 21,27 ****
#ifndef lint
#ifndef NOID
! static char privatehid[] = "@(#)private.h 7.55";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 21,27 ----
#ifndef lint
#ifndef NOID
! static char privatehid[] = "@(#)private.h 7.62";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 48,53 ****
--- 48,57 ----
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
+ #ifndef HAVE_STDINT_H
+ #define HAVE_STDINT_H (199901 <= __STDC_VERSION__)
+ #endif /* !defined HAVE_STDINT_H */
+
#ifndef HAVE_STRERROR
#define HAVE_STRERROR 1
#endif /* !defined HAVE_STRERROR */
***************
*** 89,95 ****
#include "stdio.h"
#include "errno.h"
#include "string.h"
! #include "limits.h" /* for CHAR_BIT */
#include "time.h"
#include "stdlib.h"
--- 93,99 ----
#include "stdio.h"
#include "errno.h"
#include "string.h"
! #include "limits.h" /* for CHAR_BIT et al. */
#include "time.h"
#include "stdlib.h"
***************
*** 124,129 ****
--- 128,152 ----
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+ #if HAVE_STDINT_H
+ #include <stdint.h>
+ #endif /* !HAVE_STDINT_H */
+
+ #ifndef INT_FAST64_MAX
+ #ifdef LLONG_MAX
+ typedef long long int_fast64_t;
+ #else /* !defined LLONG_MAX */
+ typedef long int_fast64_t;
+ #endif /* !defined LLONG_MAX */
+ #endif /* !defined INT_FAST64_MAX */
+
+ #ifndef INT32_MAX
+ #define INT32_MAX 0x7fffffff
+ #endif /* !defined INT32_MAX */
+ #ifndef INT32_MIN
+ #define INT32_MIN (-1 - INT32_MAX)
+ #endif /* !defined INT32_MIN */
+
/*
** Workarounds for compilers/systems.
*/
***************
*** 211,224 ****
** Private function declarations.
*/
! char * icalloc P((int nelem, int elsize));
! char * icatalloc P((char * old, const char * new));
! char * icpyalloc P((const char * string));
! char * imalloc P((int n));
! void * irealloc P((void * pointer, int size));
! void icfree P((char * pointer));
! void ifree P((char * pointer));
! char * scheck P((const char *string, char *format));
/*
** Finally, some convenience items.
--- 234,247 ----
** Private function declarations.
*/
! char * icalloc P((int nelem, int elsize));
! char * icatalloc P((char * old, const char * new));
! char * icpyalloc P((const char * string));
! char * imalloc P((int n));
! void * irealloc P((void * pointer, int size));
! void icfree P((char * pointer));
! void ifree P((char * pointer));
! const char * scheck P((const char * string, const char * format));
/*
** Finally, some convenience items.
***************
*** 310,316 ****
--- 333,359 ----
char *ctime_r P((time_t const *, char *));
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+ #ifndef YEARSPERREPEAT
+ #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
+ #endif /* !defined YEARSPERREPEAT */
+
/*
+ ** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+ */
+
+ #ifndef AVGSECSPERYEAR
+ #define AVGSECSPERYEAR 31556952
+ #endif /* !defined AVGSECSPERYEAR */
+
+ #ifndef SECSPERREPEAT
+ #define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
+ #endif /* !defined SECSPERREPEAT */
+
+ #ifndef SECSPERREPEAT_BITS
+ #define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
+ #endif /* !defined SECSPERREPEAT_BITS */
+
+ /*
** UNIX was a registered trademark of The Open Group in 2003.
*/
*** tzftp/localtime.c Thu Dec 22 09:31:14 2005
--- tzexp3/localtime.c Tue Jan 17 14:42:54 2006
***************
*** 5,11 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.97";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 5,11 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.98";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 110,115 ****
--- 110,117 ----
int timecnt;
int typecnt;
int charcnt;
+ int goback;
+ int goahead;
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
***************
*** 135,142 ****
*/
static long detzcode P((const char * codep));
static const char * getzname P((const char * strp));
! static const char * getqzname P((const char * strp, const char delim));
static const char * getnum P((const char * strp, int * nump, int min,
int max));
static const char * getsecs P((const char * strp, long * secsp));
--- 137,146 ----
*/
static long detzcode P((const char * codep));
+ static time_t detzcode64 P((const char * codep));
+ static int differ_by_repeat P((time_t t1, time_t t0));
static const char * getzname P((const char * strp));
! static const char * getqzname P((const char * strp, const int delim));
static const char * getnum P((const char * strp, int * nump, int min,
int max));
static const char * getsecs P((const char * strp, long * secsp));
***************
*** 173,179 ****
const struct tm * btmp));
static time_t transtime P((time_t janfirst, int year,
const struct rule * rulep, long offset));
! static int tzload P((const char * name, struct state * sp));
static int tzparse P((const char * name, struct state * sp,
int lastditch));
--- 177,184 ----
const struct tm * btmp));
static time_t transtime P((time_t janfirst, int year,
const struct rule * rulep, long offset));
! static int tzload P((const char * name, struct state * sp,
! int doextend));
static int tzparse P((const char * name, struct state * sp,
int lastditch));
***************
*** 234,239 ****
--- 239,257 ----
return result;
}
+ static time_t
+ detzcode64(codep)
+ const char * const codep;
+ {
+ register time_t result;
+ register int i;
+
+ result = (codep[0] & 0x80) ? ~0L : 0L;
+ for (i = 0; i < 8; ++i)
+ result = result * 256 + (codep[i] & 0xff);
+ return result;
+ }
+
static void
settzname P((void))
{
***************
*** 303,315 ****
}
static int
! tzload(name, sp)
register const char * name;
register struct state * const sp;
{
! register const char * p;
! register int i;
! register int fid;
if (name == NULL && (name = TZDEFAULT) == NULL)
return -1;
--- 321,353 ----
}
static int
! differ_by_repeat(t1, t0)
! const time_t t1;
! const time_t t0;
! {
! if (TYPE_INTEGRAL(time_t) &&
! TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
! return 0;
! return t1 - t0 == SECSPERREPEAT;
! }
!
! static int
! tzload(name, sp, doextend)
register const char * name;
register struct state * const sp;
+ register const int doextend;
{
! register const char * p;
! register int i;
! 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;
if (name == NULL && (name = TZDEFAULT) == NULL)
return -1;
***************
*** 347,364 ****
if ((fid = open(name, OPEN_MODE)) == -1)
return -1;
}
! {
! struct tzhead * tzhp;
! union {
! struct tzhead tzhead;
! char buf[sizeof *sp + sizeof *tzhp];
! } u;
int ttisstdcnt;
int ttisgmtcnt;
- i = read(fid, u.buf, sizeof u.buf);
- if (close(fid) != 0)
- return -1;
ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
--- 385,397 ----
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);
***************
*** 373,389 ****
(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
return -1;
! if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */
sp->timecnt + /* types */
! sp->typecnt * (4 + 2) + /* ttinfos */
sp->charcnt + /* chars */
! sp->leapcnt * (4 + 4) + /* lsinfos */
ttisstdcnt + /* ttisstds */
ttisgmtcnt) /* ttisgmts */
return -1;
for (i = 0; i < sp->timecnt; ++i) {
! sp->ats[i] = detzcode(p);
! p += 4;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
--- 406,424 ----
(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 */
sp->charcnt + /* chars */
! 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);
! p += stored;
}
for (i = 0; i < sp->timecnt; ++i) {
sp->types[i] = (unsigned char) *p++;
***************
*** 411,418 ****
register struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
! lsisp->ls_trans = detzcode(p);
! p += 4;
lsisp->ls_corr = detzcode(p);
p += 4;
}
--- 446,454 ----
register struct lsinfo * lsisp;
lsisp = &sp->lsis[i];
! lsisp->ls_trans = (stored == 4) ?
! detzcode(p) : detzcode64(p);
! p += stored;
lsisp->ls_corr = detzcode(p);
p += 4;
}
***************
*** 469,475 ****
--- 505,567 ----
}
break;
}
+ /*
+ ** 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.
+ */
+ if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
+ 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)
+ ts.ttis[i].tt_abbrind +=
+ sp->charcnt;
+ for (i = 0; i < ts.charcnt; ++i)
+ sp->chars[sp->charcnt++] =
+ ts.chars[i];
+ i = 0;
+ while (i < ts.timecnt &&
+ ts.ats[i] <=
+ sp->ats[sp->timecnt - 1])
+ ++i;
+ while (i < ts.timecnt &&
+ sp->timecnt < TZ_MAX_TIMES) {
+ sp->ats[sp->timecnt] =
+ ts.ats[i];
+ sp->types[sp->timecnt] =
+ sp->typecnt +
+ ts.types[i];
+ ++sp->timecnt;
+ ++i;
+ }
+ sp->ttis[sp->typecnt++] = ts.ttis[0];
+ sp->ttis[sp->typecnt++] = ts.ttis[1];
+ }
+ }
+ i = 2 * YEARSPERREPEAT;
+ sp->goback = sp->goahead = sp->timecnt > i;
+ sp->goback &= sp->types[i] == sp->types[0] &&
+ differ_by_repeat(sp->ats[i], sp->ats[0]);
+ sp->goahead &=
+ sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
+ differ_by_repeat(sp->ats[sp->timecnt - 1],
+ sp->ats[sp->timecnt - 1 - i]);
return 0;
}
***************
*** 502,520 ****
/*
** Given a pointer into an extended time zone string, scan until the ending
! ** delimiter of the zone name is located. Return a pointer to the delimiter.
**
** As with getzname above, the legal character set is actually quite
** restricted, with other characters producing undefined results.
! ** We choose not to care - allowing almost anything to be in the zone abbrev.
*/
static const char *
getqzname(strp, delim)
register const char * strp;
! const char delim;
{
! register char c;
while ((c = *strp) != '\0' && c != delim)
++strp;
--- 594,612 ----
/*
** Given a pointer into an extended time zone string, scan until the ending
! ** delimiter of the zone name is located. Return a pointer to the delimiter.
**
** As with getzname above, the legal character set is actually quite
** restricted, with other characters producing undefined results.
! ** We don't do any checking here; checking is done later in common-case code.
*/
static const char *
getqzname(strp, delim)
register const char * strp;
! const int delim;
{
! register int c;
while ((c = *strp) != '\0' && c != delim)
++strp;
***************
*** 823,831 ****
if (name == NULL)
return -1;
}
! load_result = tzload(TZDEFRULES, sp);
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
if (*name == '<') {
dstname = ++name;
--- 915,924 ----
if (name == NULL)
return -1;
}
! load_result = tzload(TZDEFRULES, sp, FALSE);
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
+ sp->timecnt = 0;
if (*name != '\0') {
if (*name == '<') {
dstname = ++name;
***************
*** 865,875 ****
return -1;
sp->typecnt = 2; /* standard time and DST */
/*
! ** Two transitions per year, from EPOCH_YEAR to 2037.
*/
- sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
- if (sp->timecnt > TZ_MAX_TIMES)
- return -1;
sp->ttis[0].tt_gmtoff = -dstoffset;
sp->ttis[0].tt_isdst = 1;
sp->ttis[0].tt_abbrind = stdlen + 1;
--- 958,965 ----
return -1;
sp->typecnt = 2; /* standard time and DST */
/*
! ** Two transitions per year, from EPOCH_YEAR forward.
*/
sp->ttis[0].tt_gmtoff = -dstoffset;
sp->ttis[0].tt_isdst = 1;
sp->ttis[0].tt_abbrind = stdlen + 1;
***************
*** 879,885 ****
atp = sp->ats;
typep = sp->types;
janfirst = 0;
! for (year = EPOCH_YEAR; year <= 2037; ++year) {
starttime = transtime(janfirst, year, &start,
stdoffset);
endtime = transtime(janfirst, year, &end,
--- 969,979 ----
atp = sp->ats;
typep = sp->types;
janfirst = 0;
! for (year = EPOCH_YEAR;
! sp->timecnt + 2 <= TZ_MAX_TIMES;
! ++year) {
! time_t newfirst;
!
starttime = transtime(janfirst, year, &start,
stdoffset);
endtime = transtime(janfirst, year, &end,
***************
*** 895,902 ****
*atp++ = endtime;
*typep++ = 1; /* DST ends */
}
! janfirst += year_lengths[isleap(year)] *
SECSPERDAY;
}
} else {
register long theirstdoffset;
--- 989,1001 ----
*atp++ = endtime;
*typep++ = 1; /* DST ends */
}
! sp->timecnt += 2;
! newfirst = janfirst;
! newfirst += year_lengths[isleap(year)] *
SECSPERDAY;
+ if (newfirst <= janfirst)
+ break;
+ janfirst = newfirst;
}
} else {
register long theirstdoffset;
***************
*** 1011,1017 ****
gmtload(sp)
struct state * const sp;
{
! if (tzload(gmt, sp) != 0)
(void) tzparse(gmt, sp, TRUE);
}
--- 1110,1116 ----
gmtload(sp)
struct state * const sp;
{
! if (tzload(gmt, sp, TRUE) != 0)
(void) tzparse(gmt, sp, TRUE);
}
***************
*** 1038,1044 ****
}
}
#endif /* defined ALL_STATE */
! if (tzload((char *) NULL, lclptr) != 0)
gmtload(lclptr);
settzname();
}
--- 1137,1143 ----
}
}
#endif /* defined ALL_STATE */
! if (tzload((char *) NULL, lclptr, TRUE) != 0)
gmtload(lclptr);
settzname();
}
***************
*** 1080,1086 ****
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(void) strcpy(lclptr->chars, gmt);
! } else if (tzload(name, lclptr) != 0)
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr);
settzname();
--- 1179,1185 ----
lclptr->ttis[0].tt_gmtoff = 0;
lclptr->ttis[0].tt_abbrind = 0;
(void) strcpy(lclptr->chars, gmt);
! } else if (tzload(name, lclptr, TRUE) != 0)
if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
(void) gmtload(lclptr);
settzname();
***************
*** 1113,1118 ****
--- 1212,1256 ----
if (sp == NULL)
return gmtsub(timep, offset, tmp);
#endif /* defined ALL_STATE */
+ if ((sp->goback && t < sp->ats[0]) ||
+ (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
+ time_t newt = t;
+ register time_t seconds;
+ register time_t tcycles;
+ register int_fast64_t icycles;
+
+ if (t < sp->ats[0])
+ seconds = sp->ats[0] - t;
+ else seconds = t - sp->ats[sp->timecnt - 1];
+ --seconds;
+ tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
+ ++tcycles;
+ icycles = tcycles;
+ if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
+ return NULL;
+ seconds = icycles;
+ seconds *= YEARSPERREPEAT;
+ seconds *= AVGSECSPERYEAR;
+ if (t < sp->ats[0])
+ newt += seconds;
+ else newt -= seconds;
+ if (newt < sp->ats[0] ||
+ newt > sp->ats[sp->timecnt - 1])
+ return NULL; /* "cannot happen" */
+ result = localsub(&newt, offset, tmp);
+ if (result == tmp) {
+ register time_t newy;
+
+ newy = tmp->tm_year;
+ if (t < sp->ats[0])
+ newy -= icycles * YEARSPERREPEAT;
+ else newy += icycles * YEARSPERREPEAT;
+ tmp->tm_year = newy;
+ if (tmp->tm_year != newy)
+ return NULL;
+ }
+ return result;
+ }
if (sp->timecnt == 0 || t < sp->ats[0]) {
i = 0;
while (sp->ttis[i].tt_isdst)
*** tzftp/zic.c Thu Dec 22 09:31:15 2005
--- tzexp3/zic.c Tue Jan 17 15:17:09 2006
***************
*** 1,15 ****
! static char elsieid[] = "@(#)zic.c 7.128";
- /*
- ** Regardless of the type of time_t, we do our work using this type.
- */
-
- typedef int zic_t;
-
#include "private.h"
#include "locale.h"
#include "tzfile.h"
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
#define ZIC_MAX_ABBR_LEN_WO_WARN 6
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
--- 1,13 ----
! static char elsieid[] = "@(#)zic.c 7.129";
#include "private.h"
#include "locale.h"
#include "tzfile.h"
+ #define ZIC_VERSION '2'
+
+ typedef int_fast64_t zic_t;
+
#ifndef ZIC_MAX_ABBR_LEN_WO_WARN
#define ZIC_MAX_ABBR_LEN_WO_WARN 6
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
***************
*** 36,41 ****
--- 34,44 ----
#define isascii(x) 1
#endif
+ #define OFFSET_STRLEN_MAXIMUM (7 + INT_STRLEN_MAXIMUM(long))
+ #define RULE_STRLEN_MAXIMUM 8 /* "Mdd.dd.d" */
+
+ #define end(cp) (strchr((cp), '\0'))
+
struct rule {
const char * r_filename;
int r_linenum;
***************
*** 44,49 ****
--- 47,54 ----
int r_loyear; /* for example, 1986 */
int r_hiyear; /* for example, 1986 */
const char * r_yrtype;
+ int r_lowasnum;
+ int r_hiwasnum;
int r_month; /* 0..11 */
***************
*** 103,111 ****
static void associate P((void));
static int ciequal P((const char * ap, const char * bp));
static void convert P((long val, char * buf));
static void dolink P((const char * fromfile, const char * tofile));
static void doabbr P((char * abbr, const char * format,
! const char * letters, int isdst));
static void eat P((const char * name, int num));
static void eats P((const char * name, int num,
const char * rname, int rnum));
--- 108,117 ----
static void associate P((void));
static int ciequal P((const char * ap, const char * bp));
static void convert P((long val, char * buf));
+ static void convert64 P((zic_t val, char * buf));
static void dolink P((const char * fromfile, const char * tofile));
static void doabbr P((char * abbr, const char * format,
! const char * letters, int isdst, int doquotes));
static void eat P((const char * name, int num));
static void eats P((const char * name, int num,
const char * rname, int rnum));
***************
*** 121,126 ****
--- 127,133 ----
static int inzcont P((char ** fields, int nfields));
static int inzone P((char ** fields, int nfields));
static int inzsub P((char ** fields, int nfields, int iscont));
+ static int is32 P((zic_t x));
static int itsabbr P((const char * abbr, const char * word));
static int itsdir P((const char * name));
static int lowerit P((int c));
***************
*** 130,135 ****
--- 137,143 ----
static long oadd P((long t1, long t2));
static void outzone P((const struct zone * zp, int ntzones));
static void puttzcode P((long code, FILE * fp));
+ static void puttzcode64 P((zic_t code, FILE * fp));
static int rcomp P((const void * leftp, const void * rightp));
static zic_t rpytime P((const struct rule * rp, int wantedy));
static void rulesub P((struct rule * rp,
***************
*** 136,145 ****
const char * loyearp, const char * hiyearp,
const char * typep, const char * monthp,
const char * dayp, const char * timep));
static void setboundaries P((void));
static zic_t tadd P((zic_t t1, long t2));
static void usage P((void));
! static void writezone P((const char * name));
static int yearistype P((int year, const char * type));
#if !HAVE_STRERROR
--- 144,158 ----
const char * loyearp, const char * hiyearp,
const char * typep, const char * monthp,
const char * dayp, const char * timep));
+ static int stringoffset P((char * result, long offset));
+ static int stringrule P((char * result, const struct rule * rp,
+ long dstoff, long gmtoff));
+ static void stringzone P((char * result,
+ const struct zone * zp, int ntzones));
static void setboundaries P((void));
static zic_t tadd P((zic_t t1, long t2));
static void usage P((void));
! static void writezone P((const char * name, const char * string));
static int yearistype P((int year, const char * type));
#if !HAVE_STRERROR
***************
*** 150,162 ****
static int errors;
static const char * filename;
static int leapcnt;
static int linenum;
static zic_t max_time;
static int max_year;
- static int max_year_representable;
static zic_t min_time;
static int min_year;
- static int min_year_representable;
static int noise;
static const char * rfilename;
static int rlinenum;
--- 163,178 ----
static int errors;
static const char * filename;
static int leapcnt;
+ static int leapseen;
+ static int leapminyear;
+ static int leapmaxyear;
static int linenum;
+ static int max_abbrvar_len;
+ static int max_format_len;
static zic_t max_time;
static int max_year;
static zic_t min_time;
static int min_year;
static int noise;
static const char * rfilename;
static int rlinenum;
***************
*** 453,459 ****
usage P((void))
{
(void) fprintf(stderr, _("%s: usage is %s \
! [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
progname, progname);
exit(EXIT_FAILURE);
--- 469,475 ----
usage P((void))
{
(void) fprintf(stderr, _("%s: usage is %s \
! [ --version ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\
\t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
progname, progname);
exit(EXIT_FAILURE);
***************
*** 464,470 ****
static const char * directory;
static const char * leapsec;
static const char * yitcommand;
- static int sflag = FALSE;
int
main(argc, argv)
--- 480,485 ----
***************
*** 486,491 ****
--- 501,511 ----
(void) textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
progname = argv[0];
+ if (TYPE_BIT(zic_t) < 64) {
+ (void) fprintf(stderr, "%s: %s\n", progname,
+ _("wild compilation-time specification of zic_t"));
+ exit(EXIT_FAILURE);
+ }
for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) {
(void) printf("%s\n", elsieid);
***************
*** 549,555 ****
noise = TRUE;
break;
case 's':
! sflag = TRUE;
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
--- 569,575 ----
noise = TRUE;
break;
case 's':
! (void) printf("%s: -s ignored\n", progname);
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
***************
*** 671,724 ****
ifree(toname);
}
! #ifndef INT_MAX
! #define INT_MAX ((int) (((unsigned)~0)>>1))
! #endif /* !defined INT_MAX */
- #ifndef INT_MIN
- #define INT_MIN ((int) ~(((unsigned)~0)>>1))
- #endif /* !defined INT_MIN */
-
- /*
- ** The tz file format currently allows at most 32-bit quantities.
- ** This restriction should be removed before signed 32-bit values
- ** wrap around in 2038, but unfortunately this will require a
- ** change to the tz file format.
- */
-
- #define MAX_BITS_IN_FILE 32
- #define TIME_T_BITS_IN_FILE ((TYPE_BIT(zic_t) < MAX_BITS_IN_FILE) ? \
- TYPE_BIT(zic_t) : MAX_BITS_IN_FILE)
-
static void
setboundaries P((void))
{
register int i;
! if (TYPE_SIGNED(zic_t)) {
! min_time = -1;
! for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
! min_time *= 2;
! max_time = -(min_time + 1);
! if (sflag)
! min_time = 0;
! } else {
! min_time = 0;
! max_time = 2 - sflag;
! for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
! max_time *= 2;
! --max_time;
! }
! {
! time_t t;
!
! t = (time_t) min_time;
! min_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
! t = (time_t) max_time;
! max_year = TM_YEAR_BASE + gmtime(&t)->tm_year;
! }
! min_year_representable = min_year;
! max_year_representable = max_year;
}
static int
--- 691,707 ----
ifree(toname);
}
! #define TIME_T_BITS_IN_FILE 64
static void
setboundaries P((void))
{
register int i;
! min_time = -1;
! for (i = 0; i < TIME_T_BITS_IN_FILE - 1; ++i)
! min_time *= 2;
! max_time = -(min_time + 1);
}
static int
***************
*** 993,998 ****
--- 976,983 ----
fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
r.r_name = ecpyalloc(fields[RF_NAME]);
r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
+ if (max_abbrvar_len < strlen(r.r_abbrvar))
+ max_abbrvar_len = strlen(r.r_abbrvar);
rules = (struct rule *) (void *) erealloc((char *) rules,
(int) ((nrules + 1) * sizeof *rules));
rules[nrules++] = r;
***************
*** 1098,1103 ****
--- 1083,1090 ----
}
z.z_rule = ecpyalloc(fields[i_rule]);
z.z_format = ecpyalloc(fields[i_format]);
+ if (max_format_len < strlen(z.z_format))
+ max_format_len = strlen(z.z_format);
hasuntil = nfields > i_untilyear;
if (hasuntil) {
z.z_untilrule.r_filename = filename;
***************
*** 1159,1164 ****
--- 1146,1156 ----
error(_("invalid leaping year"));
return;
}
+ if (!leapseen || leapmaxyear < year)
+ leapmaxyear = year;
+ if (!leapseen || leapminyear < year)
+ leapminyear = year;
+ leapseen = TRUE;
j = EPOCH_YEAR;
while (j != year) {
if (year > j) {
***************
*** 1313,1319 ****
*/
cp = loyearp;
lp = byword(cp, begin_years);
! if (lp != NULL) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_loyear = INT_MIN;
break;
--- 1305,1312 ----
*/
cp = loyearp;
lp = byword(cp, begin_years);
! rp->r_lowasnum = lp == NULL;
! if (!rp->r_lowasnum) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_loyear = INT_MIN;
break;
***************
*** 1328,1341 ****
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
error(_("invalid starting year"));
return;
- } else if (noise) {
- if (rp->r_loyear < min_year_representable)
- warning(_("starting year too low to be represented"));
- else if (rp->r_loyear > max_year_representable)
- warning(_("starting year too high to be represented"));
}
cp = hiyearp;
! if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_hiyear = INT_MIN;
break;
--- 1321,1331 ----
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
error(_("invalid starting year"));
return;
}
cp = hiyearp;
! lp = byword(cp, end_years);
! rp->r_hiwasnum = lp == NULL;
! if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
case YR_MINIMUM:
rp->r_hiyear = INT_MIN;
break;
***************
*** 1353,1363 ****
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
error(_("invalid ending year"));
return;
- } else if (noise) {
- if (rp->r_loyear < min_year_representable)
- warning(_("ending year too low to be represented"));
- else if (rp->r_loyear > max_year_representable)
- warning(_("ending year too high to be represented"));
}
if (rp->r_loyear > rp->r_hiyear) {
error(_("starting year greater than ending year"));
--- 1343,1348 ----
***************
*** 1372,1379 ****
}
rp->r_yrtype = ecpyalloc(typep);
}
- if (rp->r_loyear < min_year && rp->r_loyear > 0)
- min_year = rp->r_loyear;
/*
** Day work.
** Accept things such as:
--- 1357,1362 ----
***************
*** 1427,1433 ****
char * const buf;
{
register int i;
! register long shift;
for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
buf[i] = val >> shift;
--- 1410,1416 ----
char * const buf;
{
register int i;
! register int shift;
for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
buf[i] = val >> shift;
***************
*** 1434,1439 ****
--- 1417,1434 ----
}
static void
+ convert64(val, buf)
+ const zic_t val;
+ char * const buf;
+ {
+ register int i;
+ register int shift;
+
+ for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
+ buf[i] = val >> shift;
+ }
+
+ static void
puttzcode(val, fp)
const long val;
FILE * const fp;
***************
*** 1444,1471 ****
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
}
static int
atcomp(avp, bvp)
! void * avp;
! void * bvp;
{
! if (((struct attype *) avp)->at < ((struct attype *) bvp)->at)
! return -1;
! else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at)
! return 1;
! else return 0;
}
static void
! writezone(name)
const char * const name;
{
! register FILE * fp;
! register int i, j;
! static char * fullname;
! static struct tzhead tzh;
! zic_t ats[TZ_MAX_TIMES];
! unsigned char types[TZ_MAX_TIMES];
/*
** Sort.
--- 1439,1488 ----
(void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
}
+ static void
+ puttzcode64(val, fp)
+ const zic_t val;
+ FILE * const fp;
+ {
+ char buf[8];
+
+ convert64(val, buf);
+ (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
+ }
+
static int
atcomp(avp, bvp)
! const void * avp;
! const void * bvp;
{
! const zic_t a = ((const struct attype *) avp)->at;
! const zic_t b = ((const struct attype *) bvp)->at;
!
! return (a < b) ? -1 : (a > b);
}
+ static int
+ is32(x)
+ const zic_t x;
+ {
+ return INT32_MIN <= x && x <= INT32_MAX;
+ }
+
static void
! writezone(name, string)
const char * const name;
+ const char * const string;
{
! register FILE * fp;
! register int i, j;
! register int leapcnt32, leapi32;
! register int timecnt32, timei32;
! register int pass;
! static char * fullname;
! static const struct tzhead tzh0;
! static struct tzhead tzh;
! zic_t ats[TZ_MAX_TIMES];
! unsigned char types[TZ_MAX_TIMES];
/*
** Sort.
***************
*** 1509,1514 ****
--- 1526,1561 ----
ats[i] = attypes[i].at;
types[i] = attypes[i].type;
}
+ /*
+ ** Correct for leap seconds.
+ */
+ for (i = 0; i < timecnt; ++i) {
+ j = leapcnt;
+ while (--j >= 0)
+ if (ats[i] >= trans[j]) {
+ ats[i] = tadd(ats[i], corr[j]);
+ break;
+ }
+ }
+ /*
+ ** Figure out 32-bit-limited starts and counts.
+ */
+ timecnt32 = timecnt;
+ timei32 = 0;
+ leapcnt32 = leapcnt;
+ leapi32 = 0;
+ while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
+ --timecnt32;
+ while (timecnt32 > 0 && !is32(ats[timei32])) {
+ --timecnt32;
+ ++timei32;
+ }
+ while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
+ --leapcnt32;
+ while (leapcnt32 > 0 && !is32(trans[leapi32])) {
+ --leapcnt32;
+ ++leapi32;
+ }
fullname = erealloc(fullname,
(int) (strlen(directory) + 1 + strlen(name) + 1));
(void) sprintf(fullname, "%s/%s", directory, name);
***************
*** 1533,1599 ****
exit(EXIT_FAILURE);
}
}
! convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);
! convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
! convert(eitol(leapcnt), tzh.tzh_leapcnt);
! convert(eitol(timecnt), tzh.tzh_timecnt);
! convert(eitol(typecnt), tzh.tzh_typecnt);
! convert(eitol(charcnt), tzh.tzh_charcnt);
! (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
#define DO(field) (void) fwrite((void *) tzh.field, \
(size_t) sizeof tzh.field, (size_t) 1, fp)
! DO(tzh_magic);
! DO(tzh_reserved);
! DO(tzh_ttisgmtcnt);
! DO(tzh_ttisstdcnt);
! DO(tzh_leapcnt);
! DO(tzh_timecnt);
! DO(tzh_typecnt);
! DO(tzh_charcnt);
#undef DO
! for (i = 0; i < timecnt; ++i) {
! j = leapcnt;
! while (--j >= 0)
! if (ats[i] >= trans[j]) {
! ats[i] = tadd(ats[i], corr[j]);
! break;
}
! puttzcode((long) ats[i], fp);
}
! if (timecnt > 0)
! (void) fwrite((void *) types, (size_t) sizeof types[0],
! (size_t) timecnt, fp);
! for (i = 0; i < typecnt; ++i) {
! puttzcode((long) gmtoffs[i], fp);
! (void) putc(isdsts[i], fp);
! (void) putc(abbrinds[i], fp);
! }
! if (charcnt != 0)
! (void) fwrite((void *) chars, (size_t) sizeof chars[0],
! (size_t) charcnt, fp);
! for (i = 0; i < leapcnt; ++i) {
! if (roll[i]) {
! if (timecnt == 0 || trans[i] < ats[0]) {
! j = 0;
! while (isdsts[j])
! if (++j >= typecnt) {
! j = 0;
! break;
! }
! } else {
! j = 1;
! while (j < timecnt && trans[i] >= ats[j])
! ++j;
! j = types[j - 1];
! }
! puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
! } else puttzcode((long) trans[i], fp);
! puttzcode((long) corr[i], fp);
! }
! for (i = 0; i < typecnt; ++i)
! (void) putc(ttisstds[i], fp);
! for (i = 0; i < typecnt; ++i)
! (void) putc(ttisgmts[i], fp);
if (ferror(fp) || fclose(fp)) {
(void) fprintf(stderr, _("%s: Error writing %s\n"),
progname, fullname);
--- 1580,1699 ----
exit(EXIT_FAILURE);
}
}
! for (pass = 1; pass <= 2; ++pass) {
! register int thistimei, thistimecnt;
! register int thisleapi, thisleapcnt;
! register int thistimelim, thisleaplim;
! int writetype[TZ_MAX_TIMES];
! int typemap[TZ_MAX_TYPES];
! register int thistypecnt;
!
! if (pass == 1) {
! thistimei = timei32;
! thistimecnt = timecnt32;
! thisleapi = leapi32;
! thisleapcnt = leapcnt32;
! } else {
! thistimei = 0;
! thistimecnt = timecnt;
! thisleapi = 0;
! thisleapcnt = leapcnt;
! }
! thistimelim = thistimei + thistimecnt;
! thisleaplim = thisleapi + thisleapcnt;
! for (i = 0; i < typecnt; ++i)
! writetype[i] = thistimecnt == timecnt;
! if (thistimecnt == 0)
! writetype[types[thistimelim - 1]] = TRUE;
! else {
! for (i = thistimei - 1; i < thistimelim; ++i)
! if (i >= 0)
! writetype[types[i]] = TRUE;
! /*
! ** For America/Godthab and Antarctica/Palmer
! */
! if (thistimei == 0)
! writetype[0] = TRUE;
! }
! thistypecnt = 0;
! for (i = 0; i < typecnt; ++i)
! typemap[i] = writetype[i] ? thistypecnt++ : -1;
#define DO(field) (void) fwrite((void *) tzh.field, \
(size_t) sizeof tzh.field, (size_t) 1, fp)
! tzh = tzh0;
! (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
! tzh.tzh_version[0] = ZIC_VERSION;
! convert(eitol(thistypecnt), tzh.tzh_ttisgmtcnt);
! convert(eitol(thistypecnt), tzh.tzh_ttisstdcnt);
! convert(eitol(thisleapcnt), tzh.tzh_leapcnt);
! convert(eitol(thistimecnt), tzh.tzh_timecnt);
! convert(eitol(thistypecnt), tzh.tzh_typecnt);
! convert(eitol(charcnt), tzh.tzh_charcnt);
! DO(tzh_magic);
! DO(tzh_version);
! DO(tzh_reserved);
! DO(tzh_ttisgmtcnt);
! DO(tzh_ttisstdcnt);
! DO(tzh_leapcnt);
! DO(tzh_timecnt);
! DO(tzh_typecnt);
! DO(tzh_charcnt);
#undef DO
! for (i = thistimei; i < thistimelim; ++i)
! if (pass == 1)
! puttzcode((long) ats[i], fp);
! else puttzcode64(ats[i], fp);
! for (i = thistimei; i < thistimelim; ++i) {
! unsigned char uc;
!
! uc = typemap[types[i]];
! (void) fwrite((void *) &uc,
! (size_t) sizeof uc,
! (size_t) 1,
! fp);
! }
! for (i = 0; i < typecnt; ++i)
! if (writetype[i]) {
! puttzcode(gmtoffs[i], fp);
! (void) putc(isdsts[i], fp);
! (void) putc(abbrinds[i], fp);
}
! if (charcnt != 0)
! (void) fwrite((void *) chars, (size_t) sizeof chars[0],
! (size_t) charcnt, fp);
! for (i = thisleapi; i < thisleaplim; ++i) {
! register zic_t todo;
!
! if (roll[i]) {
! if (timecnt == 0 || trans[i] < ats[0]) {
! j = 0;
! while (isdsts[j])
! if (++j >= typecnt) {
! j = 0;
! break;
! }
! } else {
! j = 1;
! while (j < timecnt &&
! trans[i] >= ats[j])
! ++j;
! j = types[j - 1];
! }
! todo = tadd(trans[i], -gmtoffs[j]);
! } else todo = trans[i];
! if (pass == 1)
! puttzcode((long) todo, fp);
! else puttzcode64(todo, fp);
! puttzcode(corr[i], fp);
! }
! for (i = 0; i < typecnt; ++i)
! if (writetype[i])
! (void) putc(ttisstds[i], fp);
! for (i = 0; i < typecnt; ++i)
! if (writetype[i])
! (void) putc(ttisgmts[i], fp);
}
! (void) fprintf(fp, "\n%s\n", string);
if (ferror(fp) || fclose(fp)) {
(void) fprintf(stderr, _("%s: Error writing %s\n"),
progname, fullname);
***************
*** 1602,1626 ****
}
static void
! doabbr(abbr, format, letters, isdst)
char * const abbr;
const char * const format;
const char * const letters;
const int isdst;
{
! if (strchr(format, '/') == NULL) {
if (letters == NULL)
(void) strcpy(abbr, format);
else (void) sprintf(abbr, format, letters);
! } else if (isdst)
! (void) strcpy(abbr, strchr(format, '/') + 1);
! else {
! (void) strcpy(abbr, format);
! *strchr(abbr, '/') = '\0';
}
}
static void
outzone(zpfirst, zonecount)
const struct zone * const zpfirst;
const int zonecount;
--- 1702,1928 ----
}
static void
! doabbr(abbr, format, letters, isdst, doquotes)
char * const abbr;
const char * const format;
const char * const letters;
const int isdst;
+ const int doquotes;
{
! register char * cp;
! register char * slashp;
! register int len;
!
! slashp = strchr(format, '/');
! if (slashp == NULL) {
if (letters == NULL)
(void) strcpy(abbr, format);
else (void) sprintf(abbr, format, letters);
! } else if (isdst) {
! (void) strcpy(abbr, slashp + 1);
! } else {
! if (slashp > format)
! (void) strncpy(abbr, format,
! (unsigned) (slashp - format));
! abbr[slashp - format] = '\0';
}
+ if (!doquotes)
+ return;
+ for (cp = abbr; *cp != '\0'; ++cp)
+ if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", *cp) == NULL &&
+ strchr("abcdefghijklmnopqrstuvwxyz", *cp) == NULL)
+ break;
+ len = strlen(abbr);
+ if (len > 0 && *cp == '\0')
+ return;
+ abbr[len + 2] = '\0';
+ abbr[len + 1] = '>';
+ for ( ; len > 0; --len)
+ abbr[len] = abbr[len - 1];
+ abbr[0] = '<';
}
static void
+ updateminmax(x)
+ const int x;
+ {
+ if (min_year > x)
+ min_year = x;
+ if (max_year < x)
+ max_year = x;
+ }
+
+ static int
+ stringoffset(result, offset)
+ char * result;
+ long offset;
+ {
+ register int hours;
+ register int minutes;
+ register int seconds;
+
+ result[0] = '\0';
+ if (offset < 0) {
+ (void) strcpy(result, "-");
+ offset = -offset;
+ }
+ seconds = offset % SECSPERMIN;
+ offset /= SECSPERMIN;
+ minutes = offset % MINSPERHOUR;
+ offset /= MINSPERHOUR;
+ hours = offset;
+ if (hours >= HOURSPERDAY) {
+ result[0] = '\0';
+ return -1;
+ }
+ (void) sprintf(end(result), "%d", hours);
+ if (minutes != 0 || seconds != 0) {
+ (void) sprintf(end(result), ":%02d", minutes);
+ if (seconds != 0)
+ (void) sprintf(end(result), ":%02d", seconds);
+ }
+ return 0;
+ }
+
+ static int
+ stringrule(result, rp, dstoff, gmtoff)
+ char * result;
+ const struct rule * const rp;
+ const long dstoff;
+ const long gmtoff;
+ {
+ register long tod;
+
+ result = end(result);
+ if (rp->r_dycode == DC_DOM) {
+ register int month, total;
+
+ if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
+ return -1;
+ total = 0;
+ for (month = 0; month < rp->r_month; ++month)
+ total += len_months[0][month];
+ (void) sprintf(result, "J%d", total + rp->r_dayofmonth);
+ } else {
+ register int week;
+
+ if (rp->r_dycode == DC_DOWGEQ) {
+ week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
+ if ((week - 1) * DAYSPERWEEK + 1 != rp->r_dayofmonth)
+ return -1;
+ } else if (rp->r_dycode == DC_DOWLEQ) {
+ if (rp->r_dayofmonth == len_months[1][rp->r_month])
+ week = 5;
+ else {
+ week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
+ if (week * DAYSPERWEEK - 1 != rp->r_dayofmonth)
+ return -1;
+ }
+ } else return -1; /* "cannot happen" */
+ (void) sprintf(result, "M%d.%d.%d",
+ rp->r_month + 1, week, rp->r_wday);
+ }
+ tod = rp->r_tod;
+ if (rp->r_todisgmt)
+ tod += gmtoff;
+ if (rp->r_todisstd && rp->r_stdoff == 0)
+ tod += dstoff;
+ if (tod < 0) {
+ result[0] = '\0';
+ return -1;
+ }
+ if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
+ (void) strcat(result, "/");
+ if (stringoffset(end(result), tod) != 0)
+ return -1;
+ }
+ return 0;
+ }
+
+ static void
+ stringzone(result, zpfirst, zonecount)
+ char * result;
+ const struct zone * const zpfirst;
+ const int zonecount;
+ {
+ register const struct zone * zp;
+ register struct rule * rp;
+ register struct rule * stdrp;
+ register struct rule * dstrp;
+ register int i;
+ register const char * abbrvar;
+
+ result[0] = '\0';
+ zp = zpfirst + zonecount - 1;
+ stdrp = dstrp = NULL;
+ for (i = 0; i < zp->z_nrules; ++i) {
+ rp = &zp->z_rules[i];
+ if (rp->r_hiwasnum || rp->r_hiyear != INT_MAX)
+ continue;
+ if (rp->r_yrtype != NULL)
+ continue;
+ if (rp->r_stdoff == 0) {
+ if (stdrp == NULL)
+ stdrp = rp;
+ else return;
+ } else {
+ if (dstrp == NULL)
+ dstrp = rp;
+ else return;
+ }
+ }
+ if (stdrp == NULL && dstrp == NULL) {
+ /*
+ ** There are no rules running through "max".
+ ** Let's find the latest rule.
+ */
+ for (i = 0; i < zp->z_nrules; ++i) {
+ rp = &zp->z_rules[i];
+ if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear ||
+ (rp->r_hiyear == stdrp->r_hiyear &&
+ rp->r_month > stdrp->r_month))
+ stdrp = rp;
+ }
+ if (stdrp != NULL && stdrp->r_stdoff != 0)
+ return; /* We end up in DST (a POSIX no-no). */
+ /*
+ ** Horrid special case: if year is 2037,
+ ** presume this is a zone handled on a year-by-year basis;
+ ** do not try to apply a rule to the zone.
+ */
+ if (stdrp != NULL && stdrp->r_hiyear == 2037)
+ return;
+ }
+ if (stdrp == NULL && zp->z_nrules != 0)
+ return;
+ abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
+ doabbr(result, zp->z_format, abbrvar, FALSE, TRUE);
+ if (stringoffset(end(result), -zp->z_gmtoff) != 0) {
+ result[0] = '\0';
+ return;
+ }
+ if (dstrp == NULL)
+ return;
+ doabbr(end(result), zp->z_format, dstrp->r_abbrvar, TRUE, TRUE);
+ if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
+ if (stringoffset(end(result),
+ -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) {
+ result[0] = '\0';
+ return;
+ }
+ (void) strcat(result, ",");
+ if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
+ result[0] = '\0';
+ return;
+ }
+ (void) strcat(result, ",");
+ if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) {
+ result[0] = '\0';
+ return;
+ }
+ }
+
+ static void
outzone(zpfirst, zonecount)
const struct zone * const zpfirst;
const int zonecount;
***************
*** 1637,1644 ****
register int startttisstd;
register int startttisgmt;
register int type;
! char startbuf[BUFSIZ];
INITIALIZE(untiltime);
INITIALIZE(starttime);
/*
--- 1939,1955 ----
register int startttisstd;
register int startttisgmt;
register int type;
! register char * startbuf;
! register char * ab;
! register char * envvar;
! register int max_abbr_len;
! register int max_envvar_len;
+ max_abbr_len = 2 + max_format_len + max_abbrvar_len;
+ max_envvar_len = 2 * max_abbr_len + 5 * 9;
+ startbuf = emalloc(max_abbr_len + 1);
+ ab = emalloc(max_abbr_len + 1);
+ envvar = emalloc(max_envvar_len + 1);
INITIALIZE(untiltime);
INITIALIZE(starttime);
/*
***************
*** 1653,1659 ****
--- 1964,2012 ----
*/
startttisstd = FALSE;
startttisgmt = FALSE;
+ min_year = max_year = EPOCH_YEAR;
+ if (leapseen) {
+ updateminmax(leapminyear);
+ updateminmax(leapmaxyear);
+ }
for (i = 0; i < zonecount; ++i) {
+ zp = &zpfirst[i];
+ updateminmax(zp->z_untilrule.r_loyear);
+ for (j = 0; j < zp->z_nrules; ++j) {
+ rp = &zp->z_rules[j];
+ if (rp->r_lowasnum)
+ updateminmax(rp->r_loyear);
+ if (rp->r_hiwasnum)
+ updateminmax(rp->r_hiyear);
+ }
+ }
+ /*
+ ** Generate lots of data if a rule can't cover all future times.
+ */
+ stringzone(envvar, zpfirst, zonecount);
+ if (noise && envvar[0] == '\0') {
+ register char * wp;
+
+ wp = ecpyalloc(_("no POSIX environment variable for zone"));
+ wp = ecatalloc(wp, " ");
+ wp = ecatalloc(wp, zpfirst->z_name);
+ warning(wp);
+ ifree(wp);
+ }
+ if (envvar[0] == '\0') {
+ if (min_year >= INT_MIN + YEARSPERREPEAT)
+ min_year -= YEARSPERREPEAT;
+ else min_year = INT_MIN;
+ if (max_year <= INT_MAX - YEARSPERREPEAT)
+ max_year += YEARSPERREPEAT;
+ else max_year = INT_MAX;
+ }
+ /*
+ ** For the benefit of older systems, generate data through 2037.
+ */
+ if (max_year < 2037)
+ max_year = 2037;
+ for (i = 0; i < zonecount; ++i) {
/*
** A guess that may well be corrected later.
*/
***************
*** 1670,1676 ****
if (zp->z_nrules == 0) {
stdoff = zp->z_stdoff;
doabbr(startbuf, zp->z_format,
! (char *) NULL, stdoff != 0);
type = addtype(oadd(zp->z_gmtoff, stdoff),
startbuf, stdoff != 0, startttisstd,
startttisgmt);
--- 2023,2029 ----
if (zp->z_nrules == 0) {
stdoff = zp->z_stdoff;
doabbr(startbuf, zp->z_format,
! (char *) NULL, stdoff != 0, FALSE);
type = addtype(oadd(zp->z_gmtoff, stdoff),
startbuf, stdoff != 0, startttisstd,
startttisgmt);
***************
*** 1700,1706 ****
register int k;
register zic_t jtime, ktime;
register long offset;
- char buf[BUFSIZ];
INITIALIZE(ktime);
if (useuntil) {
--- 2053,2058 ----
***************
*** 1756,1779 ****
stdoff);
doabbr(startbuf, zp->z_format,
rp->r_abbrvar,
! rp->r_stdoff != 0);
continue;
}
if (*startbuf == '\0' &&
startoff == oadd(zp->z_gmtoff,
! stdoff))
doabbr(startbuf,
zp->z_format,
rp->r_abbrvar,
rp->r_stdoff !=
! 0);
}
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
! doabbr(buf, zp->z_format, rp->r_abbrvar,
! rp->r_stdoff != 0);
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
! type = addtype(offset, buf, rp->r_stdoff != 0,
rp->r_todisstd, rp->r_todisgmt);
addtt(ktime, type);
}
--- 2108,2134 ----
stdoff);
doabbr(startbuf, zp->z_format,
rp->r_abbrvar,
! rp->r_stdoff != 0,
! FALSE);
continue;
}
if (*startbuf == '\0' &&
startoff == oadd(zp->z_gmtoff,
! stdoff)) {
doabbr(startbuf,
zp->z_format,
rp->r_abbrvar,
rp->r_stdoff !=
! 0,
! FALSE);
! }
}
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
! doabbr(ab, zp->z_format, rp->r_abbrvar,
! rp->r_stdoff != 0, FALSE);
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
! type = addtype(offset, ab, rp->r_stdoff != 0,
rp->r_todisstd, rp->r_todisgmt);
addtt(ktime, type);
}
***************
*** 1806,1812 ****
starttime = tadd(starttime, -gmtoff);
}
}
! writezone(zpfirst->z_name);
}
static void
--- 2161,2170 ----
starttime = tadd(starttime, -gmtoff);
}
}
! writezone(zpfirst->z_name, envvar);
! ifree(startbuf);
! ifree(ab);
! ifree(envvar);
}
static void
***************
*** 2185,2192 ****
will not work with pre-2004 versions of zic"));
}
}
- if (dayoff < 0 && !TYPE_SIGNED(zic_t))
- return min_time;
if (dayoff < min_time / SECSPERDAY)
return min_time;
if (dayoff > max_time / SECSPERDAY)
--- 2543,2548 ----
***************
*** 2212,2218 ****
cp = string;
wp = NULL;
while (isascii((unsigned char) *cp) &&
! isalpha((unsigned char) *cp))
++cp;
if (cp - string == 0)
wp = _("time zone abbreviation lacks alphabetic at start");
--- 2568,2574 ----
cp = string;
wp = NULL;
while (isascii((unsigned char) *cp) &&
! isspace((unsigned char) *cp))
++cp;
if (cp - string == 0)
wp = _("time zone abbreviation lacks alphabetic at start");
*** tzftp/scheck.c Thu Dec 22 09:31:15 2005
--- tzexp3/scheck.c Tue Jan 17 14:42:55 2006
***************
*** 1,6 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)scheck.c 8.16";
#endif /* !defined lint */
#endif /* !defined NOID */
--- 1,6 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)scheck.c 8.17";
#endif /* !defined lint */
#endif /* !defined NOID */
***************
*** 8,27 ****
#include "private.h"
! char *
scheck(string, format)
const char * const string;
! char * const format;
{
register char * fbuf;
register const char * fp;
register char * tp;
register int c;
! register char * result;
char dummy;
- static char nada;
! result = &nada;
if (string == NULL || format == NULL)
return result;
fbuf = imalloc((int) (2 * strlen(format) + 4));
--- 8,26 ----
#include "private.h"
! const char *
scheck(string, format)
const char * const string;
! const char * const format;
{
register char * fbuf;
register const char * fp;
register char * tp;
register int c;
! register const char * result;
char dummy;
! result = "";
if (string == NULL || format == NULL)
return result;
fbuf = imalloc((int) (2 * strlen(format) + 4));
1
0
Since this is in the spring, shouldn't that last change be from 2AM CST to
3AM CDT?
++PLS
-----Original Message-----
From: tz-request(a)elsie.nci.nih.gov [mailto:tz-request@elsie.nci.nih.gov] On
Behalf Of Deborah Goldsmith
Sent: Wednesday, January 18, 2006 5:38 PM
To: tz(a)lecserver.nci.nih.gov
Subject: DOT issues final ruling on Indiana time zones
<snip>
assuming I'm interpreting everything correctly. The DOT doesn't specify
whether Starke county switch to Central Time at the appropriate time for its
old or new time zone, but I'm assuming the old here. That leads to it
falling back from 2:00AM EST to 1:00AM CST, and then again from 2:00AM CST
to 1:00AM CST. If that makes people nervous, then the transition would need
to be at 3:00 AM.
Deborah Goldsmith
Internationalization, Unicode liaison
Apple Computer, Inc.
goldsmit(a)apple.com
2
1
We use the most populous city in a zone by default; this is the same as
the case with America/New_York versus America/Washington.
--ado
-----Original Message-----
From: Paul Schauble [mailto:Paul.Schauble@ticketmaster.com]
Sent: Tuesday, January 17, 2006 6:39 PM
To: tz(a)lecserver.nci.nih.gov
Subject: Why America/Shiprock?
I was just looking at the tzdata file for the entry for the Navajo
Nation.
I'm curious why this entry is named America/Shiprock when the capitol of
the Navajo Nation is Window Rock. Can anyone enlighten me?
Thanks,
++PLS
2
1