Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6872d96

Browse files
committed
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.
1 parent 0a65b18 commit 6872d96

File tree

7 files changed

+139
-99
lines changed

7 files changed

+139
-99
lines changed

src/timezone/README

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ match properly on the old version.
5050
Time Zone code
5151
==============
5252

53-
The code in this directory is currently synced with tzcode release 2016j.
53+
The code in this directory is currently synced with tzcode release 2017b.
5454
There are many cosmetic (and not so cosmetic) differences from the
5555
original tzcode library, but diffs in the upstream version should usually
5656
be propagated to our version. Here are some notes about that.

src/timezone/localtime.c

+56-17
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
#include <fcntl.h>
1818

1919
#include "datatype/timestamp.h"
20-
#include "private.h"
2120
#include "pgtz.h"
21+
22+
#include "private.h"
2223
#include "tzfile.h"
2324

2425

@@ -414,10 +415,10 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
414415
{
415416
/*
416417
* Attempt to reuse existing abbreviations. Without this,
417-
* America/Anchorage would stop working after 2037 when
418-
* TZ_MAX_CHARS is 50, as sp->charcnt equals 42 (for LMT CAT CAWT
419-
* CAPT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
420-
* AKST AKDT). Reusing means sp->charcnt can stay 42 in this
418+
* America/Anchorage would be right on the edge after 2037 when
419+
* TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
420+
* APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
421+
* AKST AKDT). Reusing means sp->charcnt can stay 40 in this
421422
* example.
422423
*/
423424
int gotabbr = 0;
@@ -451,6 +452,17 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
451452
if (gotabbr == 2)
452453
{
453454
sp->charcnt = charcnt;
455+
456+
/*
457+
* Ignore any trailing, no-op transitions generated by zic as
458+
* they don't help here and can run afoul of bugs in zic 2016j
459+
* or earlier.
460+
*/
461+
while (1 < sp->timecnt
462+
&& (sp->types[sp->timecnt - 1]
463+
== sp->types[sp->timecnt - 2]))
464+
sp->timecnt--;
465+
454466
for (i = 0; i < ts->timecnt; i++)
455467
if (sp->ats[sp->timecnt - 1] < ts->ats[i])
456468
break;
@@ -974,6 +986,8 @@ tzparse(const char *name, struct state * sp, bool lastditch)
974986
int yearlim;
975987
int timecnt;
976988
pg_time_t janfirst;
989+
int32 janoffset = 0;
990+
int yearbeg;
977991

978992
++name;
979993
if ((name = getrule(name, &start)) == NULL)
@@ -994,8 +1008,23 @@ tzparse(const char *name, struct state * sp, bool lastditch)
9941008
sp->defaulttype = 0;
9951009
timecnt = 0;
9961010
janfirst = 0;
997-
yearlim = EPOCH_YEAR + YEARSPERREPEAT;
998-
for (year = EPOCH_YEAR; year < yearlim; year++)
1011+
yearbeg = EPOCH_YEAR;
1012+
1013+
do
1014+
{
1015+
int32 yearsecs
1016+
= year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1017+
1018+
yearbeg--;
1019+
if (increment_overflow_time(&janfirst, -yearsecs))
1020+
{
1021+
janoffset = -yearsecs;
1022+
break;
1023+
}
1024+
} while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1025+
1026+
yearlim = yearbeg + YEARSPERREPEAT + 1;
1027+
for (year = yearbeg; year < yearlim; year++)
9991028
{
10001029
int32
10011030
starttime = transtime(year, &start, stdoffset),
@@ -1020,24 +1049,34 @@ tzparse(const char *name, struct state * sp, bool lastditch)
10201049
{
10211050
if (TZ_MAX_TIMES - 2 < timecnt)
10221051
break;
1023-
yearlim = year + YEARSPERREPEAT + 1;
10241052
sp->ats[timecnt] = janfirst;
1025-
if (increment_overflow_time
1026-
(&sp->ats[timecnt], starttime))
1027-
break;
1028-
sp->types[timecnt++] = reversed;
1053+
if (!increment_overflow_time
1054+
(&sp->ats[timecnt],
1055+
janoffset + starttime))
1056+
sp->types[timecnt++] = reversed;
1057+
else if (janoffset)
1058+
sp->defaulttype = reversed;
10291059
sp->ats[timecnt] = janfirst;
1030-
if (increment_overflow_time
1031-
(&sp->ats[timecnt], endtime))
1032-
break;
1033-
sp->types[timecnt++] = !reversed;
1060+
if (!increment_overflow_time
1061+
(&sp->ats[timecnt],
1062+
janoffset + endtime))
1063+
{
1064+
sp->types[timecnt++] = !reversed;
1065+
yearlim = year + YEARSPERREPEAT + 1;
1066+
}
1067+
else if (janoffset)
1068+
sp->defaulttype = !reversed;
10341069
}
1035-
if (increment_overflow_time(&janfirst, yearsecs))
1070+
if (increment_overflow_time
1071+
(&janfirst, janoffset + yearsecs))
10361072
break;
1073+
janoffset = 0;
10371074
}
10381075
sp->timecnt = timecnt;
10391076
if (!timecnt)
10401077
sp->typecnt = 1; /* Perpetual DST. */
1078+
else if (YEARSPERREPEAT < year - yearbeg)
1079+
sp->goback = sp->goahead = true;
10411080
}
10421081
else
10431082
{

src/timezone/pgtz.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <sys/stat.h>
1818
#include <time.h>
1919

20+
#include "datatype/timestamp.h"
2021
#include "miscadmin.h"
2122
#include "pgtz.h"
2223
#include "storage/fd.h"
@@ -308,14 +309,14 @@ pg_tzset_offset(long gmtoffset)
308309
char tzname[128];
309310

310311
snprintf(offsetstr, sizeof(offsetstr),
311-
"%02ld", absoffset / SECSPERHOUR);
312-
absoffset %= SECSPERHOUR;
312+
"%02ld", absoffset / SECS_PER_HOUR);
313+
absoffset %= SECS_PER_HOUR;
313314
if (absoffset != 0)
314315
{
315316
snprintf(offsetstr + strlen(offsetstr),
316317
sizeof(offsetstr) - strlen(offsetstr),
317-
":%02ld", absoffset / SECSPERMIN);
318-
absoffset %= SECSPERMIN;
318+
":%02ld", absoffset / SECS_PER_MINUTE);
319+
absoffset %= SECS_PER_MINUTE;
319320
if (absoffset != 0)
320321
snprintf(offsetstr + strlen(offsetstr),
321322
sizeof(offsetstr) - strlen(offsetstr),

src/timezone/private.h

+57-19
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,8 @@ extern int unlink(const char *filename);
6767
* Finally, some convenience items.
6868
*/
6969

70-
#ifndef TYPE_BIT
7170
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
72-
#endif /* !defined TYPE_BIT */
73-
74-
#ifndef TYPE_SIGNED
7571
#define TYPE_SIGNED(type) (((type) -1) < 0)
76-
#endif /* !defined TYPE_SIGNED */
77-
7872
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
7973

8074
/*
@@ -88,7 +82,6 @@ extern int unlink(const char *filename);
8882
#define MINVAL(t, b) \
8983
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
9084

91-
#ifndef INT_STRLEN_MAXIMUM
9285
/*
9386
* 302 / 1000 is log10(2.0) rounded up.
9487
* Subtract one for the sign bit if the type is signed;
@@ -98,7 +91,6 @@ extern int unlink(const char *filename);
9891
#define INT_STRLEN_MAXIMUM(type) \
9992
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
10093
1 + TYPE_SIGNED(type))
101-
#endif /* !defined INT_STRLEN_MAXIMUM */
10294

10395
/*
10496
* INITIALIZE(x)
@@ -108,24 +100,70 @@ extern int unlink(const char *filename);
108100
#undef _
109101
#define _(msgid) (msgid)
110102

111-
#ifndef YEARSPERREPEAT
103+
/* Handy macros that are independent of tzfile implementation. */
104+
112105
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
113-
#endif /* !defined YEARSPERREPEAT */
106+
107+
#define SECSPERMIN 60
108+
#define MINSPERHOUR 60
109+
#define HOURSPERDAY 24
110+
#define DAYSPERWEEK 7
111+
#define DAYSPERNYEAR 365
112+
#define DAYSPERLYEAR 366
113+
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
114+
#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY)
115+
#define MONSPERYEAR 12
116+
117+
#define TM_SUNDAY 0
118+
#define TM_MONDAY 1
119+
#define TM_TUESDAY 2
120+
#define TM_WEDNESDAY 3
121+
#define TM_THURSDAY 4
122+
#define TM_FRIDAY 5
123+
#define TM_SATURDAY 6
124+
125+
#define TM_JANUARY 0
126+
#define TM_FEBRUARY 1
127+
#define TM_MARCH 2
128+
#define TM_APRIL 3
129+
#define TM_MAY 4
130+
#define TM_JUNE 5
131+
#define TM_JULY 6
132+
#define TM_AUGUST 7
133+
#define TM_SEPTEMBER 8
134+
#define TM_OCTOBER 9
135+
#define TM_NOVEMBER 10
136+
#define TM_DECEMBER 11
137+
138+
#define TM_YEAR_BASE 1900
139+
140+
#define EPOCH_YEAR 1970
141+
#define EPOCH_WDAY TM_THURSDAY
142+
143+
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
114144

115145
/*
116-
* The Gregorian year averages 365.2425 days, which is 31556952 seconds.
146+
* Since everything in isleap is modulo 400 (or a factor of 400), we know that
147+
* isleap(y) == isleap(y % 400)
148+
* and so
149+
* isleap(a + b) == isleap((a + b) % 400)
150+
* or
151+
* isleap(a + b) == isleap(a % 400 + b % 400)
152+
* This is true even if % means modulo rather than Fortran remainder
153+
* (which is allowed by C89 but not C99).
154+
* We use this to avoid addition overflow problems.
117155
*/
118156

119-
#ifndef AVGSECSPERYEAR
120-
#define AVGSECSPERYEAR 31556952L
121-
#endif /* !defined AVGSECSPERYEAR */
157+
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
122158

123-
#ifndef SECSPERREPEAT
124-
#define SECSPERREPEAT ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR)
125-
#endif /* !defined SECSPERREPEAT */
126159

127-
#ifndef SECSPERREPEAT_BITS
160+
/*
161+
* The Gregorian year averages 365.2425 days, which is 31556952 seconds.
162+
*/
163+
164+
#define AVGSECSPERYEAR 31556952L
165+
#define SECSPERREPEAT \
166+
((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR)
128167
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
129-
#endif /* !defined SECSPERREPEAT_BITS */
130168

131169
#endif /* !defined PRIVATE_H */

src/timezone/strftime.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Convert a broken-down time stamp to a string. */
1+
/* Convert a broken-down timestamp to a string. */
22

33
/*
44
* Copyright 1989 The Regents of the University of California.
@@ -44,7 +44,6 @@
4444
#include <locale.h>
4545

4646
#include "private.h"
47-
#include "tzfile.h"
4847

4948

5049
struct lc_time_T
@@ -452,11 +451,17 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
452451
{
453452
long diff;
454453
char const *sign;
454+
bool negative;
455455

456456
if (t->tm_isdst < 0)
457457
continue;
458458
diff = t->tm_gmtoff;
459-
if (diff < 0)
459+
negative = diff < 0;
460+
if (diff == 0)
461+
{
462+
negative = t->tm_zone[0] == '-';
463+
}
464+
if (negative)
460465
{
461466
sign = "-";
462467
diff = -diff;

src/timezone/tzfile.h

-52
Original file line numberDiff line numberDiff line change
@@ -100,56 +100,4 @@ struct tzhead
100100

101101
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
102102

103-
#define SECSPERMIN 60
104-
#define MINSPERHOUR 60
105-
#define HOURSPERDAY 24
106-
#define DAYSPERWEEK 7
107-
#define DAYSPERNYEAR 365
108-
#define DAYSPERLYEAR 366
109-
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
110-
#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY)
111-
#define MONSPERYEAR 12
112-
113-
#define TM_SUNDAY 0
114-
#define TM_MONDAY 1
115-
#define TM_TUESDAY 2
116-
#define TM_WEDNESDAY 3
117-
#define TM_THURSDAY 4
118-
#define TM_FRIDAY 5
119-
#define TM_SATURDAY 6
120-
121-
#define TM_JANUARY 0
122-
#define TM_FEBRUARY 1
123-
#define TM_MARCH 2
124-
#define TM_APRIL 3
125-
#define TM_MAY 4
126-
#define TM_JUNE 5
127-
#define TM_JULY 6
128-
#define TM_AUGUST 7
129-
#define TM_SEPTEMBER 8
130-
#define TM_OCTOBER 9
131-
#define TM_NOVEMBER 10
132-
#define TM_DECEMBER 11
133-
134-
#define TM_YEAR_BASE 1900
135-
136-
#define EPOCH_YEAR 1970
137-
#define EPOCH_WDAY TM_THURSDAY
138-
139-
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
140-
141-
/*
142-
* Since everything in isleap is modulo 400 (or a factor of 400), we know that
143-
* isleap(y) == isleap(y % 400)
144-
* and so
145-
* isleap(a + b) == isleap((a + b) % 400)
146-
* or
147-
* isleap(a + b) == isleap(a % 400 + b % 400)
148-
* This is true even if % means modulo rather than Fortran remainder
149-
* (which is allowed by C89 but not C99).
150-
* We use this to avoid addition overflow problems.
151-
*/
152-
153-
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
154-
155103
#endif /* !defined TZFILE_H */

0 commit comments

Comments
 (0)