[tz] question about mktime_tzname()
Paul Eggert
eggert at cs.ucla.edu
Thu Jan 12 16:41:38 UTC 2017
On 01/11/2017 02:06 PM, Arthur David Olson wrote:
> > Unfortunately now that I think of it, I see that this can't work on
> > hosts with 32-bit time_t, as they can't cover the 400-year span. So the
> > code is still broken on 32-bit hosts. Is there a better way to fix
> the code?
>
> Since 32-bit time_t values can only cover (about) 140 years, not
> covering a 400-year span's not a bug, it's a given.-)
Yes, but unfortunately the code in localtime.c filled in the table only
for the years 1970-2038, and this the 68-year filled-in period was not
enough to make the goback code work correctly (it needs 400 years). I
installed the attached patch to try to fix this; it handles Kees
Dekker's test case correctly on hosts with 32-bit time_t.
-------------- next part --------------
From 11d493ae597f7f3e41afa441b93848aa2281209c Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert at cs.ucla.edu>
Date: Thu, 12 Jan 2017 08:34:21 -0800
Subject: [PATCH] Fix bug for pre-1970 POSIX DST, 32-bit time_t
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* localtime.c (tzparse): Fill in the table before 1970, if
POSIX DST is specified. This is needed on 32-bit platforms,
since they don’t have the time_t space for a 400-year repeat.
This finishes the fix for the problem reported by Kees Dekker in:
http://mm.icann.org/pipermail/tz/2017-January/024736.html
---
localtime.c | 50 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 35 insertions(+), 15 deletions(-)
diff --git a/localtime.c b/localtime.c
index 5f63801..3967e90 100644
--- a/localtime.c
+++ b/localtime.c
@@ -1080,6 +1080,8 @@ tzparse(const char *name, struct state *sp, bool lastditch)
register int yearlim;
register int timecnt;
time_t janfirst;
+ int_fast32_t janoffset = 0;
+ int yearbeg;
++name;
if ((name = getrule(name, &start)) == NULL)
@@ -1099,8 +1101,20 @@ tzparse(const char *name, struct state *sp, bool lastditch)
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
- yearlim = EPOCH_YEAR + YEARSPERREPEAT;
- for (year = EPOCH_YEAR; year < yearlim; year++) {
+ yearbeg = EPOCH_YEAR;
+
+ do {
+ int_fast32_t yearsecs
+ = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
+ yearbeg--;
+ if (increment_overflow_time(&janfirst, -yearsecs)) {
+ janoffset = -yearsecs;
+ break;
+ }
+ } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
+
+ yearlim = yearbeg + YEARSPERREPEAT + 1;
+ for (year = yearbeg; year < yearlim; year++) {
int_fast32_t
starttime = transtime(year, &start, stdoffset),
endtime = transtime(year, &end, dstoffset);
@@ -1120,26 +1134,32 @@ tzparse(const char *name, struct state *sp, bool lastditch)
+ (stdoffset - dstoffset))))) {
if (TZ_MAX_TIMES - 2 < timecnt)
break;
- yearlim = year + YEARSPERREPEAT + 1;
sp->ats[timecnt] = janfirst;
- if (increment_overflow_time
- (&sp->ats[timecnt], starttime))
- break;
- sp->types[timecnt++] = reversed;
+ if (! increment_overflow_time
+ (&sp->ats[timecnt],
+ janoffset + starttime))
+ sp->types[timecnt++] = reversed;
+ else if (janoffset)
+ sp->defaulttype = reversed;
sp->ats[timecnt] = janfirst;
- if (increment_overflow_time
- (&sp->ats[timecnt], endtime))
- break;
- sp->types[timecnt++] = !reversed;
+ if (! increment_overflow_time
+ (&sp->ats[timecnt],
+ janoffset + endtime)) {
+ sp->types[timecnt++] = !reversed;
+ yearlim = year + YEARSPERREPEAT + 1;
+ } else if (janoffset)
+ sp->defaulttype = !reversed;
}
- if (increment_overflow_time(&janfirst, yearsecs))
+ if (increment_overflow_time
+ (&janfirst, janoffset + yearsecs))
break;
+ janoffset = 0;
}
sp->timecnt = timecnt;
- if (timecnt)
- sp->goback = sp->goahead = true;
- else
+ if (! timecnt)
sp->typecnt = 1; /* Perpetual DST. */
+ else if (YEARSPERREPEAT < year - yearbeg)
+ sp->goback = sp->goahead = true;
} else {
register int_fast32_t theirstdoffset;
register int_fast32_t theirdstoffset;
--
2.9.3
More information about the tz
mailing list