1
0
mirror of https://frontier.innolan.net/rainlance/amiga-tz.git synced 2025-11-21 23:10:14 +00:00

Support time stamps past 2038 in zones like America/Santiago.

This implements a suggestion by Arthur David Olson.
Without this change, zic -v diagnoses problems with several zones
where it cannot compute a POSIX-equivalent TZ setting for time
stamps past 2038, which means these time stamps may be mishandled.
This entails a minor change to the binary tz file format, to allow
a minor extension to the POSIX TZ setting in the binary file,
instead of requiring a pure POSIX TZ setting.  The zones fixed by
this change are America/Godthab, America/Santiago, Antarctica/Palmer,
Asia/Gaza, Asia/Hebron, Asia/Jerusalem, Pacific/Easter, and
Pacific/Fiji.  The only zone that remains unfixed is
Asia/Tehran, which schedules clock transitions via the
Iranian calendar, something that even the extended TZ
setting cannot represent.
* localtime.c (getrule): Allow transition times to be signed.
* newtzset.3: Describe the extensions to POSIX TZ strings.
Some of these extensions (e.g., hours == 26) were already
implemented but were not documented.  Give examples.
* tzfile.5: Document the relaxed restriction on the stored TZ
string; its hours component can be in the range -167..167 rather
than the POSIX-required 0..24.  Refer to newtzset(5).
* zic.c (stringoffset): Allow hours to go up to 167.
(stringrule): Be willing to generate hours in the range -167
through 167.
This commit is contained in:
Paul Eggert
2013-09-05 18:19:12 -07:00
parent bd3e920d0e
commit 07351e0248
4 changed files with 54 additions and 18 deletions

View File

@ -835,7 +835,7 @@ getrule(const char *strp, register struct rule *const rulep)
** Time specified.
*/
++strp;
strp = getsecs(strp, &rulep->r_time);
strp = getoffset(strp, &rulep->r_time);
} else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
return strp;
}

View File

@ -177,16 +177,47 @@ The
.I time
has the same format as
.I offset
except that no leading sign
except that POSIX does not allow a leading sign
.RB (`` \(mi ''
or
.RB `` \(pl '')
is allowed. The default, if
.RB `` \(pl '').
As an extension to POSIX, the hours part of
.I time
can range from \(mi167 to 167; this allows for unusual rules such
as "the Saturday before the first Sunday of March". The default, if
.I time
is not given, is
.BR 02:00:00 .
.RE
.LP
Here are some examples of
.B TZ
values that directly specify the time zone rules; they use some of the
extensions to POSIX.
.TP
.B EST5
stands for US eastern
time (EST), 5 hours behind UTC, without daylight saving.
.TP
.B FJT\(mi12FJST,M10.3.4/74,M1.3.4/75
stands for Fiji Time (FJT) and Fiji Summer Time (FJST), 12 hours ahead
of UTC, where clocks spring forward at 74:00 on the third Thursday in
October (i.e., 02:00 on the first Sunday on or after October 18), and
fall back at 75:00 on the third Thursday in January (i.e., 03:00 on
the first Sunday on or after January 18).
.TP
.B IST\(mi2IDT,M3.4.4/26,M10.5.0
stands for Israel standard time (IST) and Israel daylight time (IDT),
2 hours ahead of UTC, where clocks spring forward at 26:00 on the
fourth Thursday in March (i.e., 02:00 on the first Friday on or after
March 23), and fall back at 02:00 on the last Sunday in October.
.TP
.B WGT3WGST,M3.5.0/\(mi2,M10.5.0/\(mi1
stands for Western Greenland Time (WGT) and Western Greenland Summer
Time (WGST), 3 hours behind UTC, where clocks follow the EU rules of
springing forward the last Sunday in March at \(mi02:00 (i.e., 01:00 UTC)
and falling back the last Sunday in October at \(mi01:00 (i.e., 01:00 UTC).
.PP
If no
.I rule
is present in

View File

@ -145,7 +145,11 @@ 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).
This string may use a minor extension to the POSIX TZ format: the
hours part of its transition times may be signed and range from
\(mi167 through 167 instead of the POSIX-required unsigned values
from 0 through 24.
.SH SEE ALSO
newctime(3)
newctime(3), newtzset(3)
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.

27
zic.c
View File

@ -1776,7 +1776,7 @@ stringoffset(char *result, zic_t offset)
minutes = offset % MINSPERHOUR;
offset /= MINSPERHOUR;
hours = offset;
if (hours > HOURSPERDAY) {
if (hours >= HOURSPERDAY * DAYSPERWEEK) {
result[0] = '\0';
return -1;
}
@ -1793,7 +1793,7 @@ static int
stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
const zic_t gmtoff)
{
register zic_t tod;
register zic_t tod = rp->r_tod;
result = end(result);
if (rp->r_dycode == DC_DOM) {
@ -1807,32 +1807,33 @@ stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
(void) sprintf(result, "J%d", total + rp->r_dayofmonth);
} else {
register int week;
register int wday = rp->r_wday;
register int wdayoff;
if (rp->r_dycode == DC_DOWGEQ) {
if ((rp->r_dayofmonth % DAYSPERWEEK) != 1)
return -1;
week = 1 + rp->r_dayofmonth / DAYSPERWEEK;
wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
wday -= wdayoff;
tod += wdayoff * SECSPERDAY;
week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
} else if (rp->r_dycode == DC_DOWLEQ) {
if (rp->r_dayofmonth == len_months[1][rp->r_month])
week = 5;
else {
if ((rp->r_dayofmonth % DAYSPERWEEK) != 0)
return -1;
wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
wday -= wdayoff;
tod += wdayoff * SECSPERDAY;
week = rp->r_dayofmonth / DAYSPERWEEK;
}
} else return -1; /* "cannot happen" */
if (wday < 0)
wday += DAYSPERWEEK;
(void) sprintf(result, "M%d.%d.%d",
rp->r_month + 1, week, rp->r_wday);
rp->r_month + 1, week, 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)