1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-25 01:02:05 +03:00

Sync our copy of the timezone library with IANA release tzcode2017b.

zic no longer mishandles some transitions in January 2038 when it
attempts to work around Qt bug 53071.  This fixes a bug affecting
Pacific/Tongatapu that was introduced in zic 2016e.  localtime.c
now contains a workaround, useful when loading a file generated by
a buggy zic.

There are assorted cosmetic changes as well, notably relocation
of a bunch of #defines.
This commit is contained in:
Tom Lane
2017-04-30 15:13:51 -04:00
parent 12d11432b4
commit e18b2c480d
7 changed files with 139 additions and 99 deletions

View File

@ -17,8 +17,9 @@
#include <fcntl.h>
#include "datatype/timestamp.h"
#include "private.h"
#include "pgtz.h"
#include "private.h"
#include "tzfile.h"
@ -414,10 +415,10 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
{
/*
* Attempt to reuse existing abbreviations. Without this,
* America/Anchorage would stop working after 2037 when
* TZ_MAX_CHARS is 50, as sp->charcnt equals 42 (for LMT CAT CAWT
* CAPT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
* AKST AKDT). Reusing means sp->charcnt can stay 42 in this
* America/Anchorage would be right on the edge after 2037 when
* TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
* APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
* AKST AKDT). Reusing means sp->charcnt can stay 40 in this
* example.
*/
int gotabbr = 0;
@ -451,6 +452,17 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
if (gotabbr == 2)
{
sp->charcnt = charcnt;
/*
* Ignore any trailing, no-op transitions generated by zic as
* they don't help here and can run afoul of bugs in zic 2016j
* or earlier.
*/
while (1 < sp->timecnt
&& (sp->types[sp->timecnt - 1]
== sp->types[sp->timecnt - 2]))
sp->timecnt--;
for (i = 0; i < ts->timecnt; i++)
if (sp->ats[sp->timecnt - 1] < ts->ats[i])
break;
@ -974,6 +986,8 @@ tzparse(const char *name, struct state * sp, bool lastditch)
int yearlim;
int timecnt;
pg_time_t janfirst;
int32 janoffset = 0;
int yearbeg;
++name;
if ((name = getrule(name, &start)) == NULL)
@ -994,8 +1008,23 @@ 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
{
int32 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++)
{
int32
starttime = transtime(year, &start, stdoffset),
@ -1020,24 +1049,34 @@ tzparse(const char *name, struct state * sp, bool lastditch)
{
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->typecnt = 1; /* Perpetual DST. */
else if (YEARSPERREPEAT < year - yearbeg)
sp->goback = sp->goahead = true;
}
else
{