[tz] [PROPOSED] Don't mistruncate TZif files at leap seconds
Paul Eggert
eggert at cs.ucla.edu
Tue Sep 14 08:34:20 UTC 2021
Without this fix, zic mishandles the command
‘zic -L leapseconds -r @1706745601 etcetera’ when ‘leapseconds’
is generated from the test data file mentioned in:
https://mm.icann.org/pipermail/tz/2021-September/030385.html
The resulting, incorrect TZif file causes
‘TZ=Etc/GMT date -r 1706745601’ to output
"Thu Feb 1 00:00:01 GMT 2024" instead of the correct
"Thu Feb 1 00:00:00 GMT 2024", because localtime misinterprets
the leap second entry at 1706745601 to be a positive instead of a
negative leap second.
* NEWS: Mention the fix.
* zic.c (limitrange): When omitting leading leap seconds, do not
output a leap second table that starts with a positive leap second
with a nonpositive correction (or with a negative leap second with
a positive correction) as that will confuse TZif readers into
thinking the positive leap second is negative or vice versa.
Instead, keep otherwise-unnecessary leading leap seconds to
avoid the confusion.
---
NEWS | 6 ++++++
zic.c | 14 ++++++++++++--
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index 62a7ba2..9983f11 100644
--- a/NEWS
+++ b/NEWS
@@ -137,6 +137,12 @@ Unreleased, experimental changes
last time transition disagreed with the TZ string, contrary to
Internet RFC 8563 section 3.3.
+ Fix a bug with 'zic -r @X' when X is a negative leap second that
+ has a nonnegative correction. Without the fix, the output file
+ was truncated so that X appeared to be a positive leap second.
+ Fix a similar, even-less-likely bug when truncating at a positive
+ leap second that has a nonpositive correction.
+
zic -r now reports an error if given rolling leap seconds, as this
usage has never generally worked and is evidently unused.
diff --git a/zic.c b/zic.c
index b06ef66..c6feb8b 100644
--- a/zic.c
+++ b/zic.c
@@ -1972,12 +1972,22 @@ limitrange(struct timerange r, bool locut, zic_t lo, zic_t hi,
r.base++;
}
- /* Omit as many leap seconds < LO as possible, such that the first
- leap second in the truncated list is <= LO. */
+ /* Omit as many initial leap seconds as possible, such that the
+ first leap second in the truncated list is <= LO, and is a
+ positive leap second if and only if it has a positive correction.
+ This supports common TZif readers that assume that the first leap
+ second is positive if and only if its correction is positive. */
while (1 < r.leapcount && trans[r.leapbase + 1] <= lo) {
r.leapcount--;
r.leapbase++;
}
+ while (0 < r.leapbase
+ && ((corr[r.leapbase - 1] < corr[r.leapbase])
+ != (0 < corr[r.leapbase]))) {
+ r.leapcount++;
+ r.leapbase--;
+ }
+
/* Omit ordinary and leap second transitions greater than HI + 1. */
if (hi < ZIC_MAX) {
--
2.30.2
More information about the tz
mailing list