[tz] FW: missing extension rules

Zefram zefram at fysh.org
Tue Oct 11 22:09:06 UTC 2011


I wrote:
>I also pointed out America/Argentina/San_Luis.  It turns out that zic
>is deliberately declining to fill the POSIX-TZ field, because of the
>DSTness of the last observation.  This is the same reason why it left
>that field empty in Africa/Cairo, once it had made the mistake about
>which observation came last.  I have a plan for improving this situation,
>which I'll address in a separate patch.

Attached patch changes this behaviour.  In the case where 400 years of
explicit observations are being generated due to inability to express
the extension rule in the POSIX-TZ field, if there are actually no
observations being generated then a redundant observation is added on the
end.  This provides an explicit endpoint for the explicit observations.
Code that claims no knowledge after the final transition, like my Perl
module, are OK for 400 years.  Code that tries to repeat the last 400
years has some clue as to which 400 years to repeat.

I extended the existing exception for the case where the source lists
explicit transitions up to 2037.  The code recognises this as indicating
that the behaviour after 2037 is not expressed in the zone source,
rather than being an explicit list of transitions that actually ends
in 2037.  The code declines to fill the POSIX-TZ field in this case.
I made it also decline to add the redundant observation 400 years later.

When this is applied on top of my previous patch, the only tzfile affected
by this change is America/Argentina/San_Luis.

I reviewed all the tzfiles that have their POSIX-TZ field empty.
I believe all the remaining ones have a good excuse.  Specifically
(excluding links):

America/Santiago
Antarctica/Palmer
Pacific/Easter
	"Chile" rules, transitions on Sun>=9, can't be expressed in
	POSIX-TZ

America/Godthab
	"EU" rules, transitions at 01:00 UT which would be 22:00 or 23:00
	of previous day in local time, can't be expresssed in POSIX-TZ

Asia/Amman
	"Jordan" rules, transition at 24:00 local time, can't be expressed
	in POSIX-TZ

Asia/Jerusalem
	"Zion" rules, real rule inexpressible in source, transitions
	listed explicitly up to 2037

Asia/Tehran
	"Iran" rules, real rule inexpressible in source, transitions
	listed explicitly up to 2037

-zefram
-------------- next part --------------
diff -ur tz2011j.mod1/zic.c tz2011j.mod2/zic.c
--- tz2011j.mod1/zic.c	2011-10-11 21:34:44.000000000 +0100
+++ tz2011j.mod2/zic.c	2011-10-11 22:56:40.000000000 +0100
@@ -1968,8 +1968,11 @@
 		** presume this is a zone handled on a year-by-year basis;
 		** do not try to apply a rule to the zone.
 		*/
-		if (stdrp != NULL && stdrp->r_hiyear == 2037)
+		if (stdrp != NULL && stdrp->r_hiyear == 2037) {
+			result[0] = '!';
+			result[1] = '\0';
 			return;
+		}
 	}
 	if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0))
 		return;
@@ -2023,6 +2026,7 @@
 	register int			max_abbr_len;
 	register int			max_envvar_len;
 	register int			prodstic; /* all rules are min to max */
+	register int			do_extend;
 
 	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 	max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2067,6 +2071,9 @@
 	** Generate lots of data if a rule can't cover all future times.
 	*/
 	stringzone(envvar, zpfirst, zonecount);
+	do_extend = envvar[0] == '\0';
+	if(envvar[0] == '!' && envvar[1] == '\0')
+		envvar[0] = '\0';
 	if (noise && envvar[0] == '\0') {
 		register char *	wp;
 
@@ -2076,7 +2083,7 @@
 		warning(wp);
 		ifree(wp);
 	}
-	if (envvar[0] == '\0') {
+	if (do_extend) {
 		if (min_year >= INT_MIN + YEARSPERREPEAT)
 			min_year -= YEARSPERREPEAT;
 		else	min_year = INT_MIN;
@@ -2257,6 +2264,45 @@
 				starttime = tadd(starttime, -gmtoff);
 		}
 	}
+	if (do_extend) {
+		/*
+		** If we're extending the explicitly listed observations
+		** for 400 years because we can't fill the POSIX-TZ field,
+		** check whether we actually ended up explicitly listing
+		** observations through that period.  If there aren't any
+		** near the end of the 400-year period, add a redundant
+		** one at the end of the final year, to make it clear
+		** that we are claiming to have definite knowledge of
+		** the lack of transitions up to that point.
+		*/
+		struct rule xr;
+		int i;
+		struct attype *lastat;
+		xr.r_month = TM_JANUARY;
+		xr.r_dycode = DC_DOM;
+		xr.r_dayofmonth = 1;
+		xr.r_tod = 0;
+		for (lastat = &attypes[0], i = 1; i <= timecnt; i++)
+			if (attypes[i].at > lastat->at)
+				lastat = &attypes[i];
+		if (lastat->at < rpytime(&xr, max_year - 1)) {
+			/*
+			** Create new type code for the redundant entry,
+			** to prevent it being optimised away.
+			*/
+			if (typecnt >= TZ_MAX_TYPES) {
+				error(_("too many local time types"));
+				exit(EXIT_FAILURE);
+			}
+			gmtoffs[typecnt] = gmtoffs[lastat->type];
+			isdsts[typecnt] = isdsts[lastat->type];
+			ttisstds[typecnt] = ttisstds[lastat->type];
+			ttisgmts[typecnt] = ttisgmts[lastat->type];
+			abbrinds[typecnt] = abbrinds[lastat->type];
+			++typecnt;
+			addtt(rpytime(&xr, max_year + 1), typecnt-1);
+		}
+	}
 	writezone(zpfirst->z_name, envvar);
 	ifree(startbuf);
 	ifree(ab);


More information about the tz mailing list