mirror of
https://frontier.innolan.net/rainlance/amiga-tz.git
synced 2026-05-07 01:49:04 +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:
27
zic.c
27
zic.c
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user