[tz] Unable to compile Antarctica/Macquarie

Arthur David Olson arthurdavidolson at gmail.com
Thu May 23 17:41:40 UTC 2013


Here are possible changes to australasia, localtime.c, and zic.c
to deal with Macquarie.

Below, "current" means what's in tzcode2013c and tzdata2013c
(and the results of a "make" on those files).

australasia is changed so that if it's run through current (and earlier)
versions of zic they'll produce a binary file that give correct results
when processed by current (and earlier) versions of localtime.c

localtime.c is changed to give correct results when processing the current
binary Antarctica/Macquarie file.
I've compiled zdump using this version of localtime.c and done a "zdump -v"
on all the binary files produced by default, using the command
     cd /top/of/zoneinfo/binary/tree ; zdump -v `find * -type f -print`
and compared the results with those produced by compiling zdump with
the current localtime.c; other than for pre-1916 Macquarie times, all
results are the same.

zic.c is changed so that it produces a binary file from the current
australasia that the current localtime.c handles correctly.
The changes are bulkier than strictly necessary so that the only
change to output is for the Antarctica/Macquarie file; I've done
the relevant "diff -r" to verify that no other binary output changes.
(Basically, the zic changes arrange for Macquarie's "EST" type to appear
first
in the 32-bit portion of the binary output; since the current localtime
uses the first standard-time type for early times, the reordering
induces correct behavior.)

(The unique-in-the-existing-data aspect of Macquarie: it was "zzz" before
1899,
which falls outside the 32-bit time_t window, and re-entered "zzz" in 1948
which is within that's within the 32-bit window.)

diff output is attached and also appear below (with tabs manged).

A long-term possibility is to change zic to always output
pseudo-transition-time data for the lowest possible time_t value;
since doing that would change every binary file I did avoided that
approach today.

And...all this was done in a 32-bit environment; regression testing in
a 64-bit environment is prudent.

    @dashdashado

*** /tmp/,aaustralasia    2013-05-23 19:44:48.910652000 +0300
--- /tmp/,baustralasia    2013-05-23 19:44:49.097852300 +0300
***************
*** 230,239 ****
  # - Macquarie Island will stay on UTC+11 for winter and therefore not
  # switch back from daylight savings time when other parts of Australia do
  # on 4 April.
  Zone Antarctica/Macquarie 0    -    zzz    1899 Nov
              10:00    -    EST    1916 Oct 1 2:00
              10:00    1:00    EST    1917 Feb
!             10:00    Aus    EST    1919 Apr
              0    -    zzz    1948 Mar 25
              10:00    Aus    EST    1967
              10:00    AT    EST    2010 Apr 4 3:00
--- 230,245 ----
  # - Macquarie Island will stay on UTC+11 for winter and therefore not
  # switch back from daylight savings time when other parts of Australia do
  # on 4 April.
+ #
+ # From Arthur David Olson (2013-05-23):
+ # The 1919 transition is overspecified below so pre-2013 zics
+ # will produce a binary file with an EST-type as the first 32-bit type;
+ # this is required for correct handling of times before 1916 by
+ # pre-2013 versions of localtime.
  Zone Antarctica/Macquarie 0    -    zzz    1899 Nov
              10:00    -    EST    1916 Oct 1 2:00
              10:00    1:00    EST    1917 Feb
!             10:00    Aus    EST    1919 Apr 1 0:00s
              0    -    zzz    1948 Mar 25
              10:00    Aus    EST    1967
              10:00    AT    EST    2010 Apr 4 3:00
*** /tmp/,alocaltime.c    2013-05-23 19:44:49.285052600 +0300
--- /tmp/,blocaltime.c    2013-05-23 19:44:49.363052800 +0300
***************
*** 112,117 ****
--- 112,118 ----
      char        chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
                  (2 * (MY_TZNAME_MAX + 1)))];
      struct lsinfo    lsis[TZ_MAX_LEAPS];
+     int        defaulttype;    /* for early times or if no transitions */
  };

  struct rule {
***************
*** 582,587 ****
--- 583,622 ----
                      break;
          }
      }
+     /*
+     ** If type 0 is is unused in transitions,
+     ** it's the type to use for early times.
+     */
+     for (i = 0; i < sp->typecnt; ++i)
+         if (sp->types[i] == 0)
+             break;
+     i = (i >= sp->typecnt) ? 0 : -1;
+     /*
+     ** Absent the above,
+     ** if there are transition times
+     ** and the first transition is to a daylight time
+     ** find the standard type less than and closest to
+     ** the type of the first transition.
+     */
+     if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
+         i = sp->types[0];
+         while (--i >= 0)
+             if (!sp->ttis[i].tt_isdst)
+                 break;
+     }
+     /*
+     ** If no result yet, find the first standard type.
+     ** If there is none, punt to type zero.
+     */
+     if (i < 0) {
+         i = 0;
+         while (sp->ttis[i].tt_isdst)
+             if (++i >= sp->typecnt) {
+                 i = 0;
+                 break;
+             }
+     }
+     sp->defaulttype = i;
  #ifdef ALL_STATE
      free(up);
  #endif /* defined ALL_STATE */
***************
*** 1283,1294 ****
              return result;
      }
      if (sp->timecnt == 0 || t < sp->ats[0]) {
!         i = 0;
!         while (sp->ttis[i].tt_isdst)
!             if (++i >= sp->typecnt) {
!                 i = 0;
!                 break;
!             }
      } else {
          register int    lo = 1;
          register int    hi = sp->timecnt;
--- 1318,1324 ----
              return result;
      }
      if (sp->timecnt == 0 || t < sp->ats[0]) {
!         i = sp->defaulttype;
      } else {
          register int    lo = 1;
          register int    hi = sp->timecnt;
*** /tmp/,azic.c    2013-05-23 19:44:49.550253100 +0300
--- /tmp/,bzic.c    2013-05-23 19:44:49.643853300 +0300
***************
*** 1414,1421 ****
          fromi = 0;
          while (fromi < timecnt && attypes[fromi].at < min_time)
              ++fromi;
!         if (isdsts[0] == 0)
!             while (fromi < timecnt && attypes[fromi].type == 0)
                  ++fromi;    /* handled by default rule */
          for ( ; fromi < timecnt; ++fromi) {
              if (toi != 0 && ((attypes[fromi].at +
--- 1414,1424 ----
          fromi = 0;
          while (fromi < timecnt && attypes[fromi].at < min_time)
              ++fromi;
!         /*
!         ** Remember that type 0 is reserved.
!         */
!         if (isdsts[1] == 0)
!             while (fromi < timecnt && attypes[fromi].type == 1)
                  ++fromi;    /* handled by default rule */
          for ( ; fromi < timecnt; ++fromi) {
              if (toi != 0 && ((attypes[fromi].at +
***************
*** 1517,1523 ****
          }
          thistimelim = thistimei + thistimecnt;
          thisleaplim = thisleapi + thisleapcnt;
!         for (i = 0; i < typecnt; ++i)
              writetype[i] = thistimecnt == timecnt;
          if (thistimecnt == 0) {
              /*
--- 1520,1530 ----
          }
          thistimelim = thistimei + thistimecnt;
          thisleaplim = thisleapi + thisleapcnt;
!         /*
!         ** Remember that type 0 is reserved.
!         */
!         writetype[0] = FALSE;
!         for (i = 1; i < typecnt; ++i)
              writetype[i] = thistimecnt == timecnt;
          if (thistimecnt == 0) {
              /*
***************
*** 1533,1540 ****
              /*
              ** For America/Godthab and Antarctica/Palmer
              */
              if (thistimei == 0)
!                 writetype[0] = TRUE;
          }
  #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
          /*
--- 1540,1550 ----
              /*
              ** For America/Godthab and Antarctica/Palmer
              */
+             /*
+             ** Remember that type 0 is reserved.
+             */
              if (thistimei == 0)
!                 writetype[1] = TRUE;
          }
  #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
          /*
***************
*** 1584,1591 ****
          }
  #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
          thistypecnt = 0;
          for (i = 0; i < typecnt; ++i)
!             typemap[i] = writetype[i] ?  thistypecnt++ : -1;
          for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
              indmap[i] = -1;
          thischarcnt = 0;
--- 1594,1619 ----
          }
  #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
          thistypecnt = 0;
+         /*
+         ** Potentially, set type 0 to that of lowest-valued time.
+         */
+         if (thistimei > 0) {
+             for (i = 1; i < typecnt; ++i)
+                 if (writetype[i] && !isdsts[i])
+                     break;
+             if (i != types[thistimei - 1]) {
+                 i = types[thistimei - 1];
+                 gmtoffs[0] = gmtoffs[i];
+                 isdsts[0] = isdsts[i];
+                 ttisstds[0] = ttisstds[i];
+                 ttisgmts[0] = ttisgmts[i];
+                 abbrinds[0] = abbrinds[i];
+                 writetype[0] = TRUE;
+                 writetype[i] = FALSE;
+             }
+         }
          for (i = 0; i < typecnt; ++i)
!             typemap[i] = writetype[i] ?  thistypecnt++ : 0;
          for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
              indmap[i] = -1;
          thischarcnt = 0;
***************
*** 1942,1947 ****
--- 1970,1980 ----
          updateminmax(leapminyear);
          updateminmax(leapmaxyear + (leapmaxyear < INT_MAX));
      }
+     /*
+     ** Reserve type 0.
+     */
+     gmtoffs[0] = isdsts[0] = ttisstds[0] = ttisgmts[0] = abbrinds[0] = -1;
+     typecnt = 1;
      for (i = 0; i < zonecount; ++i) {
          zp = &zpfirst[i];
          if (i < zonecount - 1)



On Wed, May 22, 2013 at 10:21 PM, Alan Gutierrez <alan at prettyrobots.com>wrote:

> I'm compiling the TZ database using the using the `zic` from the source
> distributed with the database checked out from GitHub. I'm using the
> commit that
> relates to the `tz2013c` release. I'm not able to get an Australian EST
> timezone
> offset for dates before October 1916 for Antarctica/Macquarie.
>
> I'm using both Ruby 1.9.3p392 and GNU date 8.15.
>
> When I compile the TZ database at commit 188b29d966; "Fix times of
> habitation
> for Macquarie to agree with Tasmania history" I get the unhabited offset
> and
> abbreviation.
>
> % TZ="$PWD/build/zoneinfo/**Antarctica/Macquarie" date -d "1916/09/30
> 16:00 UTC"
> Sun Oct  1 03:00:00 EST 1916
> % TZ="$PWD/build/zoneinfo/**Antarctica/Macquarie" date -d "1916/09/30
> 15:59 UTC"
> Sat Sep 30 15:59:00 zzz 1916
>
> When I compile the TZ database at commit a676f5ad3b; "Macquarie Island is
> politically part of Australia, not Antarctica" I get the correct offset and
> abbreviation.
>
> % TZ="$PWD/build/zoneinfo/**Antarctica/Macquarie" date -d "1916/09/30
> 16:00 UTC"
> Sun Oct  1 03:00:00 EST 1916
> % TZ="$PWD/build/zoneinfo/**Antarctica/Macquarie" date -d "1916/09/30
> 15:59 UTC"
> Sun Oct  1 01:59:00 EST 1916
>
> Using this commit, if I change the date of the first line of the Zone from
> "1899
> Nov" back to "1911", it starts to work again.
> Here is the change set that causes the confusion.
>
> https://github.com/eggert/tz/**commit/**188b29d9664cfcf0384e515c69f94a**
> 2dfc27c673<https://github.com/eggert/tz/commit/188b29d9664cfcf0384e515c69f94a2dfc27c673>
>
> I am on a 32-bit system but in my experience, I'm always able to get a
> correct
> timezone offset for dates in 1916 regardless of whether or not the zone
> begins
> before the range of a 32-bit POSIX time.
>
> --
> Alan Gutierrez ~ @bigeasy
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mm.icann.org/pipermail/tz/attachments/20130523/fe361bb8/attachment-0001.html 
-------------- next part --------------
*** /tmp/,aaustralasia	2013-05-23 19:44:48.910652000 +0300
--- /tmp/,baustralasia	2013-05-23 19:44:49.097852300 +0300
***************
*** 230,239 ****
  # - Macquarie Island will stay on UTC+11 for winter and therefore not
  # switch back from daylight savings time when other parts of Australia do
  # on 4 April.
  Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
  			10:00	-	EST	1916 Oct 1 2:00
  			10:00	1:00	EST	1917 Feb
! 			10:00	Aus	EST	1919 Apr
  			0	-	zzz	1948 Mar 25
  			10:00	Aus	EST	1967
  			10:00	AT	EST	2010 Apr 4 3:00
--- 230,245 ----
  # - Macquarie Island will stay on UTC+11 for winter and therefore not
  # switch back from daylight savings time when other parts of Australia do
  # on 4 April.
+ #
+ # From Arthur David Olson (2013-05-23):
+ # The 1919 transition is overspecified below so pre-2013 zics
+ # will produce a binary file with an EST-type as the first 32-bit type;
+ # this is required for correct handling of times before 1916 by
+ # pre-2013 versions of localtime.
  Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
  			10:00	-	EST	1916 Oct 1 2:00
  			10:00	1:00	EST	1917 Feb
! 			10:00	Aus	EST	1919 Apr 1 0:00s
  			0	-	zzz	1948 Mar 25
  			10:00	Aus	EST	1967
  			10:00	AT	EST	2010 Apr 4 3:00
*** /tmp/,alocaltime.c	2013-05-23 19:44:49.285052600 +0300
--- /tmp/,blocaltime.c	2013-05-23 19:44:49.363052800 +0300
***************
*** 112,117 ****
--- 112,118 ----
  	char		chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
  				(2 * (MY_TZNAME_MAX + 1)))];
  	struct lsinfo	lsis[TZ_MAX_LEAPS];
+ 	int		defaulttype;	/* for early times or if no transitions */
  };
  
  struct rule {
***************
*** 582,587 ****
--- 583,622 ----
  					break;
  		}
  	}
+ 	/*
+ 	** If type 0 is is unused in transitions,
+ 	** it's the type to use for early times.
+ 	*/
+ 	for (i = 0; i < sp->typecnt; ++i)
+ 		if (sp->types[i] == 0)
+ 			break;
+ 	i = (i >= sp->typecnt) ? 0 : -1;
+ 	/*
+ 	** Absent the above,
+ 	** if there are transition times
+ 	** and the first transition is to a daylight time
+ 	** find the standard type less than and closest to
+ 	** the type of the first transition.
+ 	*/
+ 	if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
+ 		i = sp->types[0];
+ 		while (--i >= 0)
+ 			if (!sp->ttis[i].tt_isdst)
+ 				break;
+ 	}
+ 	/*
+ 	** If no result yet, find the first standard type.
+ 	** If there is none, punt to type zero.
+ 	*/
+ 	if (i < 0) {
+ 		i = 0;
+ 		while (sp->ttis[i].tt_isdst)
+ 			if (++i >= sp->typecnt) {
+ 				i = 0;
+ 				break;
+ 			}
+ 	}
+ 	sp->defaulttype = i;
  #ifdef ALL_STATE
  	free(up);
  #endif /* defined ALL_STATE */
***************
*** 1283,1294 ****
  			return result;
  	}
  	if (sp->timecnt == 0 || t < sp->ats[0]) {
! 		i = 0;
! 		while (sp->ttis[i].tt_isdst)
! 			if (++i >= sp->typecnt) {
! 				i = 0;
! 				break;
! 			}
  	} else {
  		register int	lo = 1;
  		register int	hi = sp->timecnt;
--- 1318,1324 ----
  			return result;
  	}
  	if (sp->timecnt == 0 || t < sp->ats[0]) {
! 		i = sp->defaulttype;
  	} else {
  		register int	lo = 1;
  		register int	hi = sp->timecnt;
*** /tmp/,azic.c	2013-05-23 19:44:49.550253100 +0300
--- /tmp/,bzic.c	2013-05-23 19:44:49.643853300 +0300
***************
*** 1414,1421 ****
  		fromi = 0;
  		while (fromi < timecnt && attypes[fromi].at < min_time)
  			++fromi;
! 		if (isdsts[0] == 0)
! 			while (fromi < timecnt && attypes[fromi].type == 0)
  				++fromi;	/* handled by default rule */
  		for ( ; fromi < timecnt; ++fromi) {
  			if (toi != 0 && ((attypes[fromi].at +
--- 1414,1424 ----
  		fromi = 0;
  		while (fromi < timecnt && attypes[fromi].at < min_time)
  			++fromi;
! 		/*
! 		** Remember that type 0 is reserved.
! 		*/
! 		if (isdsts[1] == 0)
! 			while (fromi < timecnt && attypes[fromi].type == 1)
  				++fromi;	/* handled by default rule */
  		for ( ; fromi < timecnt; ++fromi) {
  			if (toi != 0 && ((attypes[fromi].at +
***************
*** 1517,1523 ****
  		}
  		thistimelim = thistimei + thistimecnt;
  		thisleaplim = thisleapi + thisleapcnt;
! 		for (i = 0; i < typecnt; ++i)
  			writetype[i] = thistimecnt == timecnt;
  		if (thistimecnt == 0) {
  			/*
--- 1520,1530 ----
  		}
  		thistimelim = thistimei + thistimecnt;
  		thisleaplim = thisleapi + thisleapcnt;
! 		/*
! 		** Remember that type 0 is reserved.
! 		*/
! 		writetype[0] = FALSE;
! 		for (i = 1; i < typecnt; ++i)
  			writetype[i] = thistimecnt == timecnt;
  		if (thistimecnt == 0) {
  			/*
***************
*** 1533,1540 ****
  			/*
  			** For America/Godthab and Antarctica/Palmer
  			*/
  			if (thistimei == 0)
! 				writetype[0] = TRUE;
  		}
  #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
  		/*
--- 1540,1550 ----
  			/*
  			** For America/Godthab and Antarctica/Palmer
  			*/
+ 			/*
+ 			** Remember that type 0 is reserved.
+ 			*/
  			if (thistimei == 0)
! 				writetype[1] = TRUE;
  		}
  #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
  		/*
***************
*** 1584,1591 ****
  		}
  #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
  		thistypecnt = 0;
  		for (i = 0; i < typecnt; ++i)
! 			typemap[i] = writetype[i] ?  thistypecnt++ : -1;
  		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
  			indmap[i] = -1;
  		thischarcnt = 0;
--- 1594,1619 ----
  		}
  #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
  		thistypecnt = 0;
+ 		/*
+ 		** Potentially, set type 0 to that of lowest-valued time.
+ 		*/
+ 		if (thistimei > 0) {
+ 			for (i = 1; i < typecnt; ++i)
+ 				if (writetype[i] && !isdsts[i])
+ 					break;
+ 			if (i != types[thistimei - 1]) {
+ 				i = types[thistimei - 1];
+ 				gmtoffs[0] = gmtoffs[i];
+ 				isdsts[0] = isdsts[i];
+ 				ttisstds[0] = ttisstds[i];
+ 				ttisgmts[0] = ttisgmts[i];
+ 				abbrinds[0] = abbrinds[i];
+ 				writetype[0] = TRUE;
+ 				writetype[i] = FALSE;
+ 			}
+ 		}
  		for (i = 0; i < typecnt; ++i)
! 			typemap[i] = writetype[i] ?  thistypecnt++ : 0;
  		for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
  			indmap[i] = -1;
  		thischarcnt = 0;
***************
*** 1942,1947 ****
--- 1970,1980 ----
  		updateminmax(leapminyear);
  		updateminmax(leapmaxyear + (leapmaxyear < INT_MAX));
  	}
+ 	/*
+ 	** Reserve type 0.
+ 	*/
+ 	gmtoffs[0] = isdsts[0] = ttisstds[0] = ttisgmts[0] = abbrinds[0] = -1;
+ 	typecnt = 1;
  	for (i = 0; i < zonecount; ++i) {
  		zp = &zpfirst[i];
  		if (i < zonecount - 1)


More information about the tz mailing list