[tz] [PROPOSED] Fix zic bug with -r @X where X is deduced from TZ

Paul Eggert eggert at cs.ucla.edu
Mon Nov 27 19:55:04 UTC 2023


Problem reported by Ken Murchison for ‘zic -b slim -r @2145916800 asia’,
which generated an Asia/Jerusalem TZif file with a single
transition from -00 to IDT at 2145916800 (2038-01-01 00:00:00 UTC).
The transition should be to IST.
* NEWS: Mention this.
* zic.c (main): Don’t let redundant_time be lower than lo_time.
(outzone): Fix code for omitting trailing transitions when -R is
specified, which was inadvertently messed up by the 2023-10-15 fix
for Palestine after 2075.
---
 NEWS  |  3 ++-
 zic.c | 15 +++++++++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index 0d7fde80..c07cc7ad 100644
--- a/NEWS
+++ b/NEWS
@@ -37,7 +37,8 @@ Unreleased, experimental changes
 
     zic no longer mishandles data for Palestine after the year 2075.
     Previously, it incorrectly omitted post-2075 transitions that are
-    predicted for just before and just after Ramadan.
+    predicted for just before and just after Ramadan.  (Thanks to Ken
+    Murchison for debugging help.)
 
     zic now works again on Linux 2.6.16 and 2.6.17 (2006).
     (Problem reported by Rune Torgersen.)
diff --git a/zic.c b/zic.c
index e10cb21b..b260851f 100644
--- a/zic.c
+++ b/zic.c
@@ -897,7 +897,8 @@ static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
 static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
 static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
 
-/* The time specified by the -R option, defaulting to MIN_TIME.  */
+/* The time specified by the -R option, defaulting to MIN_TIME;
+   or lo_time, whichever is greater.  */
 static zic_t redundant_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
 
 /* The time specified by an Expires line, or negative if no such line.  */
@@ -1109,6 +1110,8 @@ main(int argc, char **argv)
 	  fprintf(stderr, _("%s: -R time exceeds -r cutoff\n"), progname);
 	  return EXIT_FAILURE;
 	}
+	if (redundant_time < lo_time)
+	  redundant_time = lo_time;
 	if (bloat == 0) {
 	  static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
 	  if (strcmp(bloat_default, "slim") == 0)
@@ -3442,6 +3445,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 	if (defaulttype < 0)
 	  defaulttype = 0;
 	if (!do_extend && !want_bloat()) {
+	  /* Keep trailing transitions that are no greater than this.  */
+	  zic_t keep_at_max;
+
 	  /* The earliest transition into a time governed by the TZ string.  */
 	  zic_t TZstarttime = ZIC_MAX;
 	  for (i = 0; i < timecnt; i++) {
@@ -3452,10 +3458,11 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 	  if (TZstarttime == ZIC_MAX)
 	    TZstarttime = nonTZlimtime;
 
-	  /* Omit trailing transitions deducible from the TZ string.  */
+	  /* Omit trailing transitions deducible from the TZ string,
+	     and not needed for -r or -R.  */
+	  keep_at_max = max(TZstarttime, redundant_time);
 	  for (i = j = 0; i < timecnt; i++)
-	    if (redundant_time <= attypes[i].at
-		&& attypes[i].at <= TZstarttime) {
+	    if (attypes[i].at <= keep_at_max) {
 	      attypes[j].at = attypes[i].at;
 	      attypes[j].dontmerge = (attypes[i].at == TZstarttime
 				      && (nonTZlimtype != attypes[i].type
-- 
2.40.1



More information about the tz mailing list