[tz] tzcode-2014c breaks applications that use the binary tz files

Paul Eggert eggert at cs.ucla.edu
Sat May 24 02:16:17 UTC 2014


gunther Vermeir wrote:
> just +1 for using the big bang...
> because "time stamps before then are physically suspect anyway." :)

Yes, I love this one!  Just yesterday I was talking to an undergraduate 
UCLA computer science student about cosmological inflation, and now I 
can go back to him and tell him I squashed a Brazilian time stamp bug 
with the Big Bang!

I'm attaching a patch which I've pushed into the experimental 
repository.  This patch uses a more-justifiable estimate for the time of 
the Big Bang, namely the Planck+WP+highL+BAO best fit.  I've tested this 
with the 2014c database and verified that it doesn't change the zdump 
output.  I've also tested that it works around the GNOME bug for 
America/Sao_Paulo on Fedora 20 x86-64 (which uses Glib 2.38).

Comments welcome.  I'd like to generate a new tz version soon, since the 
GNOME bug is reasonably painful.
-------------- next part --------------
From 36e8cd61ea4c9b177019bc607d2b10d887d8c9bb Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert at cs.ucla.edu>
Date: Fri, 23 May 2014 22:56:18 -0300
Subject: [PATCH] zic: work around GNOME bug by refusing to go back before the
 Big Bang

This works around Gnome bug 730332
<https://bugzilla.gnome.org/show_bug.cgi?id=730332>.
zic 2014c introduced the idea of generating a transition at the
minimum time value -2**63, to avoid ambiguities about what to do
before the first real transition.  Through Glib release 2.40, the
interval_end function of Glib's gtimezone.c subtracts one from
this, to find the end time of the zeroth interval (i.e., the
interval containing all the "early" time stamps); this subtraction
typically overflows and wraps around to 2**63 - 1, which causes
Glib to go off the rails and assume that all time stamps are
"early".  For example, Glib computes Sao Paulo time stamps as if
Brazil's circa-1913 rules were still in effect.
(Thanks to Leonardo Chiquitto for reporting the bug.)
Work around the bug by not generating time stamps equal to -2**63.
Come to think of it, time stamps before the Big Bang are physically
suspect anyway, so don't generate time stamps before the Big Bang.
* Makefile (GCC_DEBUG_FLAGS): Add comment re BIG_BANG.
* NEWS, zic.8 (NOTES): Document this.
* zic.c (BIG_BANG): New macro.
(big_bang_time): New constant.
(writezone, outzone, addtt): Compare to big_bang_time, not to
min_time, when deciding whether to output a time stamp.
---
 Makefile |  1 +
 NEWS     |  9 +++++++++
 zic.8    |  6 ++++++
 zic.c    | 40 ++++++++++++++++++++++++++++++++++------
 4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 3cdd845..a566c64 100644
--- a/Makefile
+++ b/Makefile
@@ -100,6 +100,7 @@ YEARISTYPE=	./yearistype
 LDLIBS=
 
 # Add the following to the end of the "CFLAGS=" line as needed.
+#  -DBIG_BANG=-9999999LL if the Big Bang occurred at time -9999999 (see zic.c)
 #  -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?)
 #  -DHAVE_DOS_FILE_NAMES if file names have drive specifiers etc. (MS-DOS)
 #  -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS
diff --git a/NEWS b/NEWS
index 6f6581b..95db5f9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,15 @@
 News for the tz database
 
 
+Unreleased, experimental changes
+
+  Changes affecting code
+
+    zic no longer generates files containing time stamps before the Big Bang.
+    This works around GNOME bug 730332
+    <https://bugzilla.gnome.org/show_bug.cgi?id=730332>.
+
+
 Release 2014c - 2014-05-13 07:44:13 -0700
 
   Changes affecting near-future time stamps
diff --git a/zic.8 b/zic.8
index ca29fd1..4e0bac8 100644
--- a/zic.8
+++ b/zic.8
@@ -519,6 +519,12 @@ 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
+Time stamps 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 time stamps are
+physically suspect anyway.  The estimated time of the Big Bang is
+approximate and may change in future versions.
 .SH FILE
 /usr/local/etc/zoneinfo	standard directory used for created files
 .SH "SEE ALSO"
diff --git a/zic.c b/zic.c
index 7e0f97f..6112002 100644
--- a/zic.c
+++ b/zic.c
@@ -723,6 +723,34 @@ warning(_("hard link failed, symbolic link used"));
 static const zic_t min_time = (zic_t) -1 << (TIME_T_BITS_IN_FILE - 1);
 static const zic_t max_time = -1 - ((zic_t) -1 << (TIME_T_BITS_IN_FILE - 1));
 
+/* Estimated time of the Big Bang, in seconds since the POSIX epoch.
+   zic does not output time stamps before this, partly because they
+   are physically suspect, and partly because GNOME mishandles them; see
+   GNOME bug 730332 <https://bugzilla.gnome.org/show_bug.cgi?id=730332>.
+
+   The following estimate for the Big Bang time is taken from:
+
+   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
+   <http://arxiv.org/pdf/1303.5062v1> [PDF]
+
+   Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO best fit,
+   gives the value 13.7965.  Multiplying this by 1000000000 and then
+   by 31557600 (the number of seconds in an astronomical year), yields
+   435384428400000000.  This estimate intentionally ignores the
+   difference between the POSIX epoch and the paper's publication
+   date, as being beneath the paper's precision.
+
+   This estimate is approximate, and may change in future versions.
+   Please do not rely on its exact value.  */
+
+#ifndef BIG_BANG
+#define BIG_BANG (-435384428400000000LL)
+#endif
+
+static const zic_t big_bang_time = BIG_BANG;
+
 static int
 itsdir(const char *const name)
 {
@@ -1478,7 +1506,7 @@ writezone(const char *const name, const char *const string, char version)
 
 		toi = 0;
 		fromi = 0;
-		while (fromi < timecnt && attypes[fromi].at < min_time)
+		while (fromi < timecnt && attypes[fromi].at < big_bang_time)
 			++fromi;
 		for ( ; fromi < timecnt; ++fromi) {
 			if (toi > 1 && ((attypes[fromi].at +
@@ -2167,9 +2195,9 @@ outzone(const struct zone * const zpfirst, const int zonecount)
 		*/
 		stdoff = 0;
 		zp = &zpfirst[i];
-		usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
+		usestart = i > 0 && (zp - 1)->z_untiltime > big_bang_time;
 		useuntil = i < (zonecount - 1);
-		if (useuntil && zp->z_untiltime <= min_time)
+		if (useuntil && zp->z_untiltime <= big_bang_time)
 			continue;
 		gmtoff = zp->z_gmtoff;
 		eat(zp->z_filename, zp->z_linenum);
@@ -2185,7 +2213,7 @@ outzone(const struct zone * const zpfirst, const int zonecount)
 			if (usestart) {
 				addtt(starttime, type);
 				usestart = FALSE;
-			} else	addtt(min_time, type);
+			} else	addtt(big_bang_time, type);
 		} else for (year = min_year; year <= max_year; ++year) {
 			if (useuntil && year > zp->z_untilrule.r_hiyear)
 				break;
@@ -2362,8 +2390,8 @@ error(_("can't determine time zone abbreviation to use just after until time"));
 static void
 addtt(const zic_t starttime, int type)
 {
-	if (starttime <= min_time ||
-		(timecnt == 1 && attypes[0].at < min_time)) {
+	if (starttime <= big_bang_time ||
+		(timecnt == 1 && attypes[0].at < big_bang_time)) {
 		gmtoffs[0] = gmtoffs[type];
 		isdsts[0] = isdsts[type];
 		ttisstds[0] = ttisstds[type];
-- 
1.9.1


More information about the tz mailing list