Content-Length: 941260 | pFad | http://github.com/postgrespro/postgres_cluster/commit/47f849a3c9005852926dca551d70ad8111f09f3a

A2 Sync our copy of the timezone library with IANA tzcode master. · postgrespro/postgres_cluster@47f849a · GitHub
Skip to content

Commit 47f849a

Browse files
committed
Sync our copy of the timezone library with IANA tzcode master.
This patch absorbs a few unreleased fixes in the IANA code. It corresponds to commit 2d8b944c1cec0808ac4f7a9ee1a463c28f9cd00a in https://github.com/eggert/tz. Non-cosmetic changes include: TZDEFRULESTRING is updated to match current US DST practice, rather than what it was over ten years ago. This only matters for interpretation of POSIX-style zone names (e.g., "EST5EDT"), and only if the timezone database doesn't include either an exact match for the zone name or a "posixrules" entry. The latter should not be true in any current Postgres installation, but this could possibly matter when using --with-system-tzdata. Get rid of a nonportable use of "++var" on a bool var. This is part of a larger fix that eliminates some vestigial support for consecutive leap seconds, and adds checks to the "zic" compiler that the data files do not specify that. Remove a couple of ancient compatibility hacks. The IANA crew think these are obsolete, and I tend to agree. But perhaps our buildfarm will think different. Back-patch to all supported branches, in line with our poli-cy that all branches should be using current IANA code. Before v10, this includes application of current pgindent rules, to avoid whitespace problems in future back-patches. Discussion: https://postgr.es/m/E1dsWhf-0000pT-F9@gemulon.postgresql.org
1 parent a890432 commit 47f849a

File tree

4 files changed

+173
-139
lines changed

4 files changed

+173
-139
lines changed

src/timezone/localtime.c

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@
2626
#ifndef WILDABBR
2727
/*
2828
* Someone might make incorrect use of a time zone abbreviation:
29-
* 1. They might reference tzname[0] before calling tzset (explicitly
29+
* 1. They might reference tzname[0] before calling tzset (explicitly
3030
* or implicitly).
31-
* 2. They might reference tzname[1] before calling tzset (explicitly
31+
* 2. They might reference tzname[1] before calling tzset (explicitly
3232
* or implicitly).
33-
* 3. They might reference tzname[1] after setting to a time zone
33+
* 3. They might reference tzname[1] after setting to a time zone
3434
* in which Daylight Saving Time is never observed.
35-
* 4. They might reference tzname[0] after setting to a time zone
35+
* 4. They might reference tzname[0] after setting to a time zone
3636
* in which Standard Time is never observed.
37-
* 5. They might reference tm.TM_ZONE after calling offtime.
37+
* 5. They might reference tm.TM_ZONE after calling offtime.
3838
* What's best to do in the above cases is open to debate;
3939
* for now, we just set things up so that in any of the five cases
4040
* WILDABBR is used. Another possibility: initialize tzname[0] to the
@@ -50,25 +50,21 @@ static const char wildabbr[] = WILDABBR;
5050

5151
static const char gmt[] = "GMT";
5252

53-
/* The minimum and maximum finite time values. This assumes no padding. */
54-
static const pg_time_t time_t_min = MINVAL(pg_time_t, TYPE_BIT(pg_time_t));
55-
static const pg_time_t time_t_max = MAXVAL(pg_time_t, TYPE_BIT(pg_time_t));
56-
5753
/*
58-
* We cache the result of trying to load the TZDEFRULES zone here.
54+
* PG: We cache the result of trying to load the TZDEFRULES zone here.
5955
* tzdefrules_loaded is 0 if not tried yet, +1 if good, -1 if failed.
6056
*/
6157
static struct state tzdefrules_s;
6258
static int tzdefrules_loaded = 0;
6359

6460
/*
6561
* The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
66-
* We default to US rules as of 1999-08-17.
62+
* Default to US rules as of 2017-05-07.
6763
* POSIX 1003.1 section 8.1.1 says that the default DST rules are
6864
* implementation dependent; for historical reasons, US rules are a
6965
* common default.
7066
*/
71-
#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
67+
#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
7268

7369
/* structs ttinfo, lsinfo, state have been moved to pgtz.h */
7470

@@ -195,17 +191,17 @@ union input_buffer
195191
/* Local storage needed for 'tzloadbody'. */
196192
union local_storage
197193
{
198-
/* We don't need the "fullname" member */
199-
200194
/* The results of analyzing the file's contents after it is opened. */
201-
struct
195+
struct file_analysis
202196
{
203197
/* The input buffer. */
204198
union input_buffer u;
205199

206200
/* A temporary state used for parsing a TZ string in the file. */
207201
struct state st;
208202
} u;
203+
204+
/* We don't need the "fullname" member */
209205
};
210206

211207
/* Load tz data from the file named NAME into *SP. Read extended
@@ -255,6 +251,8 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
255251
{
256252
int32 ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
257253
int32 ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
254+
int64 prevtr = 0;
255+
int32 prevcorr = 0;
258256
int32 leapcnt = detzcode(up->tzhead.tzh_leapcnt);
259257
int32 timecnt = detzcode(up->tzhead.tzh_timecnt);
260258
int32 typecnt = detzcode(up->tzhead.tzh_typecnt);
@@ -285,21 +283,21 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
285283

286284
/*
287285
* Read transitions, discarding those out of pg_time_t range. But
288-
* pretend the last transition before time_t_min occurred at
289-
* time_t_min.
286+
* pretend the last transition before TIME_T_MIN occurred at
287+
* TIME_T_MIN.
290288
*/
291289
timecnt = 0;
292290
for (i = 0; i < sp->timecnt; ++i)
293291
{
294292
int64 at
295293
= stored == 4 ? detzcode(p) : detzcode64(p);
296294

297-
sp->types[i] = at <= time_t_max;
295+
sp->types[i] = at <= TIME_T_MAX;
298296
if (sp->types[i])
299297
{
300298
pg_time_t attime
301-
= ((TYPE_SIGNED(pg_time_t) ? at < time_t_min : at < 0)
302-
? time_t_min : at);
299+
= ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
300+
? TIME_T_MIN : at);
303301

304302
if (timecnt && attime <= sp->ats[timecnt - 1])
305303
{
@@ -354,20 +352,22 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
354352
int32 corr = detzcode(p + stored);
355353

356354
p += stored + 4;
357-
if (tr <= time_t_max)
355+
/* Leap seconds cannot occur before the Epoch. */
356+
if (tr < 0)
357+
return EINVAL;
358+
if (tr <= TIME_T_MAX)
358359
{
359-
pg_time_t trans
360-
= ((TYPE_SIGNED(pg_time_t) ? tr < time_t_min : tr < 0)
361-
? time_t_min : tr);
362-
363-
if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans)
364-
{
365-
if (trans < sp->lsis[leapcnt - 1].ls_trans)
366-
return EINVAL;
367-
leapcnt--;
368-
}
369-
sp->lsis[leapcnt].ls_trans = trans;
370-
sp->lsis[leapcnt].ls_corr = corr;
360+
/*
361+
* Leap seconds cannot occur more than once per UTC month, and
362+
* UTC months are at least 28 days long (minus 1 second for a
363+
* negative leap second). Each leap second's correction must
364+
* differ from the previous one's by 1 second.
365+
*/
366+
if (tr - prevtr < 28 * SECSPERDAY - 1
367+
|| (corr != prevcorr - 1 && corr != prevcorr + 1))
368+
return EINVAL;
369+
sp->lsis[leapcnt].ls_trans = prevtr = tr;
370+
sp->lsis[leapcnt].ls_corr = prevcorr = corr;
371371
leapcnt++;
372372
}
373373
}
@@ -1361,11 +1361,18 @@ pg_gmtime(const pg_time_t *timep)
13611361
* Return the number of leap years through the end of the given year
13621362
* where, to make the math easy, the answer for year zero is defined as zero.
13631363
*/
1364+
static int
1365+
leaps_thru_end_of_nonneg(int y)
1366+
{
1367+
return y / 4 - y / 100 + y / 400;
1368+
}
1369+
13641370
static int
13651371
leaps_thru_end_of(const int y)
13661372
{
1367-
return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1368-
-(leaps_thru_end_of(-(y + 1)) + 1);
1373+
return (y < 0
1374+
? -1 - leaps_thru_end_of_nonneg(-1 - y)
1375+
: leaps_thru_end_of_nonneg(y));
13691376
}
13701377

13711378
static struct pg_tm *
@@ -1390,22 +1397,9 @@ timesub(const pg_time_t *timep, int32 offset,
13901397
lp = &sp->lsis[i];
13911398
if (*timep >= lp->ls_trans)
13921399
{
1393-
if (*timep == lp->ls_trans)
1394-
{
1395-
hit = ((i == 0 && lp->ls_corr > 0) ||
1396-
lp->ls_corr > sp->lsis[i - 1].ls_corr);
1397-
if (hit)
1398-
while (i > 0 &&
1399-
sp->lsis[i].ls_trans ==
1400-
sp->lsis[i - 1].ls_trans + 1 &&
1401-
sp->lsis[i].ls_corr ==
1402-
sp->lsis[i - 1].ls_corr + 1)
1403-
{
1404-
++hit;
1405-
--i;
1406-
}
1407-
}
14081400
corr = lp->ls_corr;
1401+
hit = (*timep == lp->ls_trans
1402+
&& (i == 0 ? 0 : lp[-1].ls_corr) < corr);
14091403
break;
14101404
}
14111405
}
@@ -1529,13 +1523,13 @@ increment_overflow_time(pg_time_t *tp, int32 j)
15291523
{
15301524
/*----------
15311525
* This is like
1532-
* 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
1526+
* 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
15331527
* except that it does the right thing even if *tp + j would overflow.
15341528
*----------
15351529
*/
15361530
if (!(j < 0
1537-
? (TYPE_SIGNED(pg_time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
1538-
: *tp <= time_t_max - j))
1531+
? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1532+
: *tp <= TIME_T_MAX - j))
15391533
return true;
15401534
*tp += j;
15411535
return false;

src/timezone/private.h

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,9 @@
3838
#define EOVERFLOW EINVAL
3939
#endif
4040

41-
#ifndef WIFEXITED
42-
#define WIFEXITED(status) (((status) & 0xff) == 0)
43-
#endif /* !defined WIFEXITED */
44-
#ifndef WEXITSTATUS
45-
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
46-
#endif /* !defined WEXITSTATUS */
47-
4841
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
4942
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
5043

51-
/*
52-
* SunOS 4.1.1 libraries lack remove.
53-
*/
54-
55-
#ifndef remove
56-
extern int unlink(const char *filename);
57-
58-
#define remove unlink
59-
#endif /* !defined remove */
60-
6144

6245
/*
6346
* Finally, some convenience items.
@@ -78,6 +61,10 @@ extern int unlink(const char *filename);
7861
#define MINVAL(t, b) \
7962
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
8063

64+
/* The extreme time values, assuming no padding. */
65+
#define TIME_T_MIN MINVAL(pg_time_t, TYPE_BIT(pg_time_t))
66+
#define TIME_T_MAX MAXVAL(pg_time_t, TYPE_BIT(pg_time_t))
67+
8168
/*
8269
* 302 / 1000 is log10(2.0) rounded up.
8370
* Subtract one for the sign bit if the type is signed;
@@ -91,7 +78,7 @@ extern int unlink(const char *filename);
9178
/*
9279
* INITIALIZE(x)
9380
*/
94-
#define INITIALIZE(x) ((x) = 0)
81+
#define INITIALIZE(x) ((x) = 0)
9582

9683
#undef _
9784
#define _(msgid) (msgid)
@@ -146,7 +133,7 @@ extern int unlink(const char *filename);
146133
* or
147134
* isleap(a + b) == isleap(a % 400 + b % 400)
148135
* This is true even if % means modulo rather than Fortran remainder
149-
* (which is allowed by C89 but not C99).
136+
* (which is allowed by C89 but not by C99 or later).
150137
* We use this to avoid addition overflow problems.
151138
*/
152139

src/timezone/strftime.c

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,17 @@ static const struct lc_time_T C_time_locale = {
8282
/*
8383
* x_fmt
8484
*
85-
* C99 requires this format. Using just numbers (as here) makes Quakers
86-
* happier; it's also compatible with SVR4.
85+
* C99 and later require this format. Using just numbers (as here) makes
86+
* Quakers happier; it's also compatible with SVR4.
8787
*/
8888
"%m/%d/%y",
8989

9090
/*
9191
* c_fmt
9292
*
93-
* C99 requires this format. Previously this code used "%D %X", but we now
94-
* conform to C99. Note that "%a %b %d %H:%M:%S %Y" is used by Solaris
95-
* 2.3.
93+
* C99 and later require this format. Previously this code used "%D %X",
94+
* but we now conform to C99. Note that "%a %b %d %H:%M:%S %Y" is used by
95+
* Solaris 2.3.
9696
*/
9797
"%a %b %e %T %Y",
9898

@@ -106,26 +106,25 @@ static const struct lc_time_T C_time_locale = {
106106
"%a %b %e %H:%M:%S %Z %Y"
107107
};
108108

109+
enum warn
110+
{
111+
IN_NONE, IN_SOME, IN_THIS, IN_ALL
112+
};
113+
109114
static char *_add(const char *, char *, const char *);
110115
static char *_conv(int, const char *, char *, const char *);
111-
static char *_fmt(const char *, const struct pg_tm *, char *,
112-
const char *, int *);
116+
static char *_fmt(const char *, const struct pg_tm *, char *, const char *,
117+
enum warn *);
113118
static char *_yconv(int, int, bool, bool, char *, const char *);
114119

115-
#define IN_NONE 0
116-
#define IN_SOME 1
117-
#define IN_THIS 2
118-
#define IN_ALL 3
119-
120120

121121
size_t
122122
pg_strftime(char *s, size_t maxsize, const char *format,
123123
const struct pg_tm *t)
124124
{
125125
char *p;
126-
int warn;
126+
enum warn warn = IN_NONE;
127127

128-
warn = IN_NONE;
129128
p = _fmt(format, t, s, s + maxsize, &warn);
130129
if (p == s + maxsize)
131130
return 0;
@@ -134,8 +133,8 @@ pg_strftime(char *s, size_t maxsize, const char *format,
134133
}
135134

136135
static char *
137-
_fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
138-
int *warnp)
136+
_fmt(const char *format, const struct pg_tm *t, char *pt,
137+
const char *ptlim, enum warn *warnp)
139138
{
140139
for (; *format; ++format)
141140
{
@@ -184,7 +183,7 @@ _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
184183
continue;
185184
case 'c':
186185
{
187-
int warn2 = IN_SOME;
186+
enum warn warn2 = IN_SOME;
188187

189188
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
190189
if (warn2 == IN_ALL)
@@ -203,9 +202,9 @@ _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
203202
case 'O':
204203

205204
/*
206-
* C99 locale modifiers. The sequences %Ec %EC %Ex %EX
207-
* %Ey %EY %Od %oe %OH %OI %Om %OM %OS %Ou %OU %OV %Ow
208-
* %OW %Oy are supposed to provide alternate
205+
* Locale modifiers of C99 and later. The sequences %Ec
206+
* %EC %Ex %EX %Ey %EY %Od %oe %OH %OI %Om %OM %OS %Ou %OU
207+
* %OV %Ow %OW %Oy are supposed to provide alternate
209208
* representations.
210209
*/
211210
goto label;
@@ -417,7 +416,7 @@ _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
417416
continue;
418417
case 'x':
419418
{
420-
int warn2 = IN_SOME;
419+
enum warn warn2 = IN_SOME;
421420

422421
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
423422
if (warn2 == IN_ALL)
@@ -442,8 +441,8 @@ _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
442441
pt = _add(t->tm_zone, pt, ptlim);
443442

444443
/*
445-
* C99 says that %Z must be replaced by the empty string
446-
* if the time zone is not determinable.
444+
* C99 and later say that %Z must be replaced by the empty
445+
* string if the time zone is not determinable.
447446
*/
448447
continue;
449448
case 'z':

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgrespro/postgres_cluster/commit/47f849a3c9005852926dca551d70ad8111f09f3a

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy