[tz] [PROPOSED] Remove Big Bang hack

Paul Eggert eggert at cs.ucla.edu
Wed Jun 13 10:06:27 UTC 2018


The Big Bang hack introduced in 2013d should no longer be needed,
now that type 0 is the default type and types are reordered to
make this happen.  I.e., since we now have a better fix for the
Macquarie Island problem reported by Alan Gutierrez in
<https://mm.icann.org/pipermail/tz/2013-May/019368.html>,
we can revert much of the 2013-05-23 12:19:13 -0700 change “Rework
to avoid problem with Australia/Macquarie on 32-bit hosts” and the
2014-05-01 16:32:16 -0700 followup change “zic: improve handling
of low-valued time stamps” which caused zic to insert a dummy
transition.  As a result, zic now generates TZif files that are
typically a few bytes shorter, as they were in 2013c and earlier.
* Makefile, zic.8: Remove mention of Big Bang.
* NEWS: Mention.
* zic.c (BIG_BANG, WORK_AROUND_CLIENT_OVERFLOW_BUGS, early_time):
Remove.  All uses removed.
(writezone): New arg DEFAULTTYPE.  All callers changed.
Simplify by not inserting a dummy transition before the Big Bang.
(outzone): Compute default type for use by writezone.
(addtt): Don’t second-guess type 0.
---
 Makefile |   1 -
 NEWS     |   6 +++
 zic.8    |   6 ---
 zic.c    | 151 ++++++++++++++++-----------------------------------------------
 4 files changed, 44 insertions(+), 120 deletions(-)

diff --git a/Makefile b/Makefile
index 3705fc0..2289dff 100644
--- a/Makefile
+++ b/Makefile
@@ -173,7 +173,6 @@ LDLIBS=
 
 # Add the following to the end of the "CFLAGS=" line as needed to override
 # defaults specified in the source code.  "-DFOO" is equivalent to "-DFOO=1".
-#  -DBIG_BANG=-9999999LL if the Big Bang occurred at time -9999999 (see zic.c)
 #  -DDEPRECATE_TWO_DIGIT_YEARS for optional runtime warnings about strftime
 #	formats that generate only the last two digits of year numbers
 #  -DEPOCH_LOCAL if the 'time' function returns local time not UT
diff --git a/NEWS b/NEWS
index b90e68c..87f675e 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,12 @@ Unreleased, experimental changes
     legacy zones EST5EDT, CST6CDT, MST7MDT, PST8PDT, CET, MET, and
     EET, which previously used nonzero types for these timestamps.
 
+    Because of the type 0 change, zic no longer outputs a dummy
+    transition at time -2**59 (before the Big Bang), as clients should
+    no longer need this to handle historical timestamps correctly.
+    This reverts a change introduced in 2013d and shrinks most TZif
+    files by a few bytes.
+
     localtime.c no longer requires at least one time type in TZif
     files that lack transitions or have a POSIX-style TZ string.  This
     future-proofs the code against possible future extensions to the
diff --git a/zic.8 b/zic.8
index ba4796e..00d4267 100644
--- a/zic.8
+++ b/zic.8
@@ -591,12 +591,6 @@ produces a single transition to daylight saving at the new UT offset
 To get separate transitions
 use multiple zone continuation lines
 specifying transition instants using universal time.
-.PP
-timestamps well before the Big Bang are silently omitted from the output.
-This works around bugs in software that mishandles large negative time
-stamps.  Call it sour grapes, but pre-Big-Bang timestamps are
-physically suspect anyway.  The pre-Big-Bang cutoff time is
-approximate and may change in future versions.
 .SH FILES
 .ta \w'/usr/share/zoneinfo\0\0'u
 /etc/localtime	default local time zone file
diff --git a/zic.c b/zic.c
index fd73f66..88153db 100644
--- a/zic.c
+++ b/zic.c
@@ -948,48 +948,6 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink)
 static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
 static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
 
-/* Estimated time of the Big Bang, in seconds since the POSIX epoch.
-   rounded downward to the negation of a power of two that is
-   comfortably outside the error bounds.
-
-   For the time of the Big Bang, see:
-
-   Ade PAR, Aghanim N, Armitage-Caplan C et al.  Planck 2013 results.
-   I. Overview of products and scientific results.
-   arXiv:1303.5062 2013-03-20 20:10:01 UTC
-   <https://arxiv.org/pdf/1303.5062v1> [PDF]
-
-   Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits
-   gives the value 13.798 plus-or-minus 0.037 billion years.
-   Multiplying this by 1000000000 and then by 31557600 (the number of
-   seconds in an astronomical year) gives a value that is comfortably
-   less than 2**59, so BIG_BANG is - 2**59.
-
-   BIG_BANG is approximate, and may change in future versions.
-   Please do not rely on its exact value.  */
-
-#ifndef BIG_BANG
-#define BIG_BANG (- (1LL << 59))
-#endif
-
-/* If true, work around GNOME glib bug 878
-   <https://gitlab.gnome.org/GNOME/glib/issues/878>
-   by refusing to output timestamps before BIG_BANG.
-   Such timestamps are physically suspect anyway.
-   The glib bug is scheduled to be fixed in glib 2.58.
-   There is a similar bug in 32-bit glibc 2.27 and earlier
-   <https://sourceware.org/bugzilla/show_bug.cgi?id=19738>
-   that is scheduled to be fixed in glibc 2.28;
-   unfortunately a similar bug might persist in 64-bit glibc
-   though this has not been verified.  With all this in mind,
-   let's hope that the workaround will no longer be needed
-   in the year 2025.  */
-enum { WORK_AROUND_CLIENT_OVERFLOW_BUGS = true };
-
-static const zic_t early_time = (WORK_AROUND_CLIENT_OVERFLOW_BUGS
-				 ? BIG_BANG
-				 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
-
 /* Return true if NAME is a directory.  */
 static bool
 itsdir(char const *name)
@@ -1775,7 +1733,8 @@ swaptypes(int i, int j)
 }
 
 static void
-writezone(const char *const name, const char *const string, char version)
+writezone(const char *const name, const char *const string, char version,
+	  int defaulttype)
 {
 	register FILE *			fp;
 	register ptrdiff_t		i, j;
@@ -1805,13 +1764,11 @@ writezone(const char *const name, const char *const string, char version)
 
 		toi = 0;
 		fromi = 0;
-		while (fromi < timecnt && attypes[fromi].at < early_time)
-			++fromi;
 		for ( ; fromi < timecnt; ++fromi) {
-			if (toi > 1 && ((attypes[fromi].at +
+			if (toi != 0 && ((attypes[fromi].at +
 				gmtoffs[attypes[toi - 1].type]) <=
-				(attypes[toi - 1].at +
-				gmtoffs[attypes[toi - 2].type]))) {
+				(attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
+				: attypes[toi - 2].type]))) {
 					attypes[toi - 1].type =
 						attypes[fromi].type;
 					continue;
@@ -1919,8 +1876,8 @@ writezone(const char *const name, const char *const string, char version)
 	for (pass = 1; pass <= 2; ++pass) {
 		register ptrdiff_t thistimei, thistimecnt, thistimelim;
 		register int	thisleapi, thisleapcnt, thisleaplim;
-		int old0, new0;
-		char		omittype[TZ_MAX_TYPES + 1];
+		int old0;
+		char		omittype[TZ_MAX_TYPES];
 		int		typemap[TZ_MAX_TYPES];
 		register int	thistypecnt;
 		char		thischars[TZ_MAX_CHARS];
@@ -1945,45 +1902,17 @@ writezone(const char *const name, const char *const string, char version)
 		  error(_("too many transition times"));
 		thistimelim = thistimei + thistimecnt;
 		thisleaplim = thisleapi + thisleapcnt;
-		memset(omittype, thistimecnt != timecnt, typecnt);
-		if (thistimecnt == 0) {
-			/*
-			** No transition times fall in the current
-			** (32- or 64-bit) window.
-			*/
-			if (typecnt != 0)
-			  omittype[typecnt - 1] = false;
-		} else {
-			for (i = thistimei - 1; i < thistimelim; ++i)
-				if (i >= 0)
-				  omittype[types[i]] = false;
-			/*
-			** For America/Godthab and Antarctica/Palmer
-			*/
-			if (thistimei == 0)
-			  omittype[0] = false;
-		}
-
-		/* Reorder types to make type 0 the first-used standard type
-		   if one is used, otherwise the first-used DST type if one
-		   is used, otherwise no reordering.  Use TYPEMAP to swap
-		   OLD0 and NEW0 so that NEW0 appears as type 0 in the output
-		   instead of OLD0.  TYPEMAP also omits unused types.  */
-		omittype[typecnt] = false;  /* strlen sentinel */
+		memset(omittype, true, typecnt);
+		omittype[defaulttype] = false;
+		for (i = thistimei; i < thistimelim; i++)
+		  omittype[types[i]] = false;
+
+		/* Reorder types to make DEFAULTTYPE type 0.
+		   Use TYPEMAP to swap OLD0 and DEFAULTTYPE so that
+		   DEFAULTTYPE appears as type 0 in the output instead
+		   of OLD0.  TYPEMAP also omits unused types.  */
 		old0 = strlen(omittype);
-		new0 = -1;
-		for (i = 0; i < timecnt; i++)
-		  if (!omittype[types[i]]) {
-		    if (! isdsts[types[i]]) {
-		      new0 = types[i];
-		      break;
-		    }
-		    if (new0 < 0)
-		      new0 = types[i];
-		  }
-		if (new0 < 0)
-		  new0 = old0;
-		swaptypes(old0, new0);
+		swaptypes(old0, defaulttype);
 
 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
 		/*
@@ -2035,7 +1964,8 @@ writezone(const char *const name, const char *const string, char version)
 		thistypecnt = 0;
 		for (i = old0; i < typecnt; i++)
 		  if (!omittype[i])
-		    typemap[i == old0 ? new0 : i == new0 ? old0 : i]
+		    typemap[i == old0 ? defaulttype
+			    : i == defaulttype ? old0 : i]
 		      = thistypecnt++;
 
 		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
@@ -2133,7 +2063,7 @@ writezone(const char *const name, const char *const string, char version)
 		for (i = old0; i < typecnt; i++)
 			if (!omittype[i])
 				putc(ttisgmts[i], fp);
-		swaptypes(old0, new0);
+		swaptypes(old0, defaulttype);
 	}
 	fprintf(fp, "\n%s\n", string);
 	close_file(fp, directory, name);
@@ -2487,6 +2417,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 	zic_t one = 1;
 	zic_t y2038_boundary = one << 31;
 	zic_t max_year0;
+	int defaulttype = -1;
 
 	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 	max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2595,9 +2526,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 		*/
 		stdoff = 0;
 		zp = &zpfirst[i];
-		usestart = i > 0 && (zp - 1)->z_untiltime > early_time;
+		usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
 		useuntil = i < (zonecount - 1);
-		if (useuntil && zp->z_untiltime <= early_time)
+		if (useuntil && zp->z_untiltime <= min_time)
 			continue;
 		gmtoff = zp->z_gmtoff;
 		eat(zp->z_filename, zp->z_linenum);
@@ -2612,7 +2543,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 			if (usestart) {
 				addtt(starttime, type);
 				usestart = false;
-			} else	addtt(early_time, type);
+			} else
+				defaulttype = type;
 		} else for (year = min_year; year <= max_year; ++year) {
 			if (useuntil && year > zp->z_untilrule.r_hiyear)
 				break;
@@ -2726,6 +2658,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 				offset = oadd(zp->z_gmtoff, rp->r_stdoff);
 				type = addtype(offset, ab, rp->r_isdst,
 					rp->r_todisstd, rp->r_todisgmt);
+				if (defaulttype < 0 && !rp->r_isdst)
+				  defaulttype = type;
 				if (rp->r_hiyear == ZIC_MAX
 				    && ! (0 <= lastatmax
 					  && ktime < attypes[lastatmax].at))
@@ -2742,11 +2676,14 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 			eat(zp->z_filename, zp->z_linenum);
 			if (*startbuf == '\0')
 error(_("can't determine time zone abbreviation to use just after until time"));
-			else	addtt(starttime,
-					addtype(startoff, startbuf,
-						startoff != zp->z_gmtoff,
-						startttisstd,
-						startttisgmt));
+			else {
+			  bool isdst = startoff != zp->z_gmtoff;
+			  type = addtype(startoff, startbuf, isdst,
+					 startttisstd, startttisgmt);
+			  if (defaulttype < 0 && !isdst)
+			    defaulttype = type;
+			  addtt(starttime, type);
+			}
 		}
 		/*
 		** Now we may get to set starttime for the next zone line.
@@ -2761,6 +2698,8 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 				starttime = tadd(starttime, -gmtoff);
 		}
 	}
+	if (defaulttype < 0)
+	  defaulttype = 0;
 	if (0 <= lastatmax)
 	  attypes[lastatmax].dontmerge = true;
 	if (do_extend) {
@@ -2788,7 +2727,7 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 			attypes[timecnt - 1].dontmerge = true;
 		}
 	}
-	writezone(zpfirst->z_name, envvar, version);
+	writezone(zpfirst->z_name, envvar, version, defaulttype);
 	free(startbuf);
 	free(ab);
 	free(envvar);
@@ -2797,20 +2736,6 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 static void
 addtt(zic_t starttime, int type)
 {
-	if (starttime <= early_time
-	    || (timecnt == 1 && attypes[0].at < early_time)) {
-		gmtoffs[0] = gmtoffs[type];
-		isdsts[0] = isdsts[type];
-		ttisstds[0] = ttisstds[type];
-		ttisgmts[0] = ttisgmts[type];
-		if (abbrinds[type] != 0)
-			strcpy(chars, &chars[abbrinds[type]]);
-		abbrinds[0] = 0;
-		charcnt = strlen(chars) + 1;
-		typecnt = 1;
-		timecnt = 0;
-		type = 0;
-	}
 	attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
 	attypes[timecnt].at = starttime;
 	attypes[timecnt].dontmerge = false;
-- 
2.7.4



More information about the tz mailing list