blob: 6d8c46e748133f1ce166ea4b85ad306e9469a813 [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001From 12bfb778ce688fc662a6cb35f6298734fcf4856f Mon Sep 17 00:00:00 2001
2From: Tom Lane <tgl@sss.pgh.pa.us>
3Date: Fri, 19 Oct 2018 19:36:34 -0400
4Subject: [PATCH] Sync our copy of the timezone library with IANA release
5 tzcode2018f.
6
7About half of this is purely cosmetic changes to reduce the diff between
8our code and theirs, like inserting "const" markers where they have them.
9
10The other half is tracking actual code changes in zic.c and localtime.c.
11I don't think any of these represent near-term compatibility hazards, but
12it seems best to stay up to date.
13
14I also fixed longstanding bugs in our code for producing the
15known_abbrevs.txt list, which by chance hadn't been exposed before,
16but which resulted in some garbage output after applying the upstream
17changes in zic.c. Notably, because upstream removed their old phony
18transitions at the Big Bang, it's now necessary to cope with TZif files
19containing no DST transition times at all.
20
21Upstream-Status: Backport
22Signed-off-by: Armin Kuster <akuster@mvista.com>
23
24---
25 src/timezone/README | 2 +-
26 src/timezone/localtime.c | 126 ++++++++++++------
27 src/timezone/pgtz.h | 10 +-
28 src/timezone/private.h | 3 +
29 src/timezone/strftime.c | 10 +-
30 src/timezone/tzfile.h | 7 +-
31 src/timezone/zic.c | 330 ++++++++++++++++++++++++++---------------------
32 7 files changed, 291 insertions(+), 197 deletions(-)
33
34Index: postgresql-10.5/src/timezone/README
35===================================================================
36--- postgresql-10.5.orig/src/timezone/README
37+++ postgresql-10.5/src/timezone/README
38@@ -55,7 +55,7 @@ match properly on the old version.
39 Time Zone code
40 ==============
41
42-The code in this directory is currently synced with tzcode release 2018e.
43+The code in this directory is currently synced with tzcode release 2018f.
44 There are many cosmetic (and not so cosmetic) differences from the
45 original tzcode library, but diffs in the upstream version should usually
46 be propagated to our version. Here are some notes about that.
47Index: postgresql-10.5/src/timezone/localtime.c
48===================================================================
49--- postgresql-10.5.orig/src/timezone/localtime.c
50+++ postgresql-10.5/src/timezone/localtime.c
51@@ -1,3 +1,5 @@
52+/* Convert timestamp from pg_time_t to struct pg_tm. */
53+
54 /*
55 * This file is in the public domain, so clarified as of
56 * 1996-06-05 by Arthur David Olson.
57@@ -117,7 +119,7 @@ init_ttinfo(struct ttinfo *s, int32 gmto
58 }
59
60 static int32
61-detzcode(const char *codep)
62+detzcode(const char *const codep)
63 {
64 int32 result;
65 int i;
66@@ -143,7 +145,7 @@ detzcode(const char *codep)
67 }
68
69 static int64
70-detzcode64(const char *codep)
71+detzcode64(const char *const codep)
72 {
73 uint64 result;
74 int i;
75@@ -258,8 +260,13 @@ tzloadbody(char const *name, char *canon
76 int32 charcnt = detzcode(up->tzhead.tzh_charcnt);
77 char const *p = up->buf + tzheadsize;
78
79+ /*
80+ * Although tzfile(5) currently requires typecnt to be nonzero,
81+ * support future formats that may allow zero typecnt in files that
82+ * have a TZ string and no transitions.
83+ */
84 if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
85- && 0 < typecnt && typecnt < TZ_MAX_TYPES
86+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
87 && 0 <= timecnt && timecnt < TZ_MAX_TIMES
88 && 0 <= charcnt && charcnt < TZ_MAX_CHARS
89 && (ttisstdcnt == typecnt || ttisstdcnt == 0)
90@@ -416,8 +423,7 @@ tzloadbody(char const *name, char *canon
91 struct state *ts = &lsp->u.st;
92
93 up->buf[nread - 1] = '\0';
94- if (tzparse(&up->buf[1], ts, false)
95- && ts->typecnt == 2)
96+ if (tzparse(&up->buf[1], ts, false))
97 {
98 /*
99 * Attempt to reuse existing abbreviations. Without this,
100@@ -430,7 +436,7 @@ tzloadbody(char const *name, char *canon
101 int gotabbr = 0;
102 int charcnt = sp->charcnt;
103
104- for (i = 0; i < 2; i++)
105+ for (i = 0; i < ts->typecnt; i++)
106 {
107 char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
108 int j;
109@@ -455,7 +461,7 @@ tzloadbody(char const *name, char *canon
110 }
111 }
112 }
113- if (gotabbr == 2)
114+ if (gotabbr == ts->typecnt)
115 {
116 sp->charcnt = charcnt;
117
118@@ -470,7 +476,8 @@ tzloadbody(char const *name, char *canon
119 sp->timecnt--;
120
121 for (i = 0; i < ts->timecnt; i++)
122- if (sp->ats[sp->timecnt - 1] < ts->ats[i])
123+ if (sp->timecnt == 0
124+ || sp->ats[sp->timecnt - 1] < ts->ats[i])
125 break;
126 while (i < ts->timecnt
127 && sp->timecnt < TZ_MAX_TIMES)
128@@ -481,11 +488,13 @@ tzloadbody(char const *name, char *canon
129 sp->timecnt++;
130 i++;
131 }
132- sp->ttis[sp->typecnt++] = ts->ttis[0];
133- sp->ttis[sp->typecnt++] = ts->ttis[1];
134+ for (i = 0; i < ts->typecnt; i++)
135+ sp->ttis[sp->typecnt++] = ts->ttis[i];
136 }
137 }
138 }
139+ if (sp->typecnt == 0)
140+ return EINVAL;
141 if (sp->timecnt > 1)
142 {
143 for (i = 1; i < sp->timecnt; ++i)
144@@ -507,6 +516,18 @@ tzloadbody(char const *name, char *canon
145 }
146
147 /*
148+ * Infer sp->defaulttype from the data. Although this default type is
149+ * always zero for data from recent tzdb releases, things are trickier for
150+ * data from tzdb 2018e or earlier.
151+ *
152+ * The first set of heuristics work around bugs in 32-bit data generated
153+ * by tzdb 2013c or earlier. The workaround is for zones like
154+ * Australia/Macquarie where timestamps before the first transition have a
155+ * time type that is not the earliest standard-time type. See:
156+ * https://mm.icann.org/pipermail/tz/2013-May/019368.html
157+ */
158+
159+ /*
160 * If type 0 is unused in transitions, it's the type to use for early
161 * times.
162 */
163@@ -529,6 +550,11 @@ tzloadbody(char const *name, char *canon
164 }
165
166 /*
167+ * The next heuristics are for data generated by tzdb 2018e or earlier,
168+ * for zones like EST5EDT where the first transition is to DST.
169+ */
170+
171+ /*
172 * If no result yet, find the first standard type. If there is none, punt
173 * to type zero.
174 */
175@@ -542,7 +568,14 @@ tzloadbody(char const *name, char *canon
176 break;
177 }
178 }
179+
180+ /*
181+ * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
182+ * worry about 2018e-or-earlier data. Even simpler would be to remove the
183+ * defaulttype member and just use 0 in its place.
184+ */
185 sp->defaulttype = i;
186+
187 return 0;
188 }
189
190@@ -601,10 +634,11 @@ static const int year_lengths[2] = {
191 };
192
193 /*
194- * Given a pointer into a time zone string, scan until a character that is not
195- * a valid character in a zone name is found. Return a pointer to that
196- * character.
197+ * Given a pointer into a timezone string, scan until a character that is not
198+ * a valid character in a time zone abbreviation is found.
199+ * Return a pointer to that character.
200 */
201+
202 static const char *
203 getzname(const char *strp)
204 {
205@@ -617,15 +651,17 @@ getzname(const char *strp)
206 }
207
208 /*
209- * Given a pointer into an extended time zone string, scan until the ending
210- * delimiter of the zone name is located. Return a pointer to the delimiter.
211+ * Given a pointer into an extended timezone string, scan until the ending
212+ * delimiter of the time zone abbreviation is located.
213+ * Return a pointer to the delimiter.
214 *
215 * As with getzname above, the legal character set is actually quite
216 * restricted, with other characters producing undefined results.
217 * We don't do any checking here; checking is done later in common-case code.
218 */
219+
220 static const char *
221-getqzname(const char *strp, int delim)
222+getqzname(const char *strp, const int delim)
223 {
224 int c;
225
226@@ -635,13 +671,14 @@ getqzname(const char *strp, int delim)
227 }
228
229 /*
230- * Given a pointer into a time zone string, extract a number from that string.
231+ * Given a pointer into a timezone string, extract a number from that string.
232 * Check that the number is within a specified range; if it is not, return
233 * NULL.
234 * Otherwise, return a pointer to the first character not part of the number.
235 */
236+
237 static const char *
238-getnum(const char *strp, int *nump, int min, int max)
239+getnum(const char *strp, int *const nump, const int min, const int max)
240 {
241 char c;
242 int num;
243@@ -663,14 +700,15 @@ getnum(const char *strp, int *nump, int
244 }
245
246 /*
247- * Given a pointer into a time zone string, extract a number of seconds,
248+ * Given a pointer into a timezone string, extract a number of seconds,
249 * in hh[:mm[:ss]] form, from the string.
250 * If any error occurs, return NULL.
251 * Otherwise, return a pointer to the first character not part of the number
252 * of seconds.
253 */
254+
255 static const char *
256-getsecs(const char *strp, int32 *secsp)
257+getsecs(const char *strp, int32 *const secsp)
258 {
259 int num;
260
261@@ -704,13 +742,14 @@ getsecs(const char *strp, int32 *secsp)
262 }
263
264 /*
265- * Given a pointer into a time zone string, extract an offset, in
266+ * Given a pointer into a timezone string, extract an offset, in
267 * [+-]hh[:mm[:ss]] form, from the string.
268 * If any error occurs, return NULL.
269 * Otherwise, return a pointer to the first character not part of the time.
270 */
271+
272 static const char *
273-getoffset(const char *strp, int32 *offsetp)
274+getoffset(const char *strp, int32 *const offsetp)
275 {
276 bool neg = false;
277
278@@ -730,13 +769,14 @@ getoffset(const char *strp, int32 *offse
279 }
280
281 /*
282- * Given a pointer into a time zone string, extract a rule in the form
283+ * Given a pointer into a timezone string, extract a rule in the form
284 * date[/time]. See POSIX section 8 for the format of "date" and "time".
285 * If a valid rule is not found, return NULL.
286 * Otherwise, return a pointer to the first character not part of the rule.
287 */
288+
289 static const char *
290-getrule(const char *strp, struct rule *rulep)
291+getrule(const char *strp, struct rule *const rulep)
292 {
293 if (*strp == 'J')
294 {
295@@ -795,9 +835,10 @@ getrule(const char *strp, struct rule *r
296 * Given a year, a rule, and the offset from UT at the time that rule takes
297 * effect, calculate the year-relative time that rule takes effect.
298 */
299+
300 static int32
301-transtime(int year, const struct rule *rulep,
302- int32 offset)
303+transtime(const int year, const struct rule *const rulep,
304+ const int32 offset)
305 {
306 bool leapyear;
307 int32 value;
308@@ -981,7 +1022,7 @@ tzparse(const char *name, struct state *
309 {
310 dstname = name;
311 name = getzname(name);
312- dstlen = name - dstname; /* length of DST zone name */
313+ dstlen = name - dstname; /* length of DST abbr. */
314 }
315 if (!dstlen)
316 return false;
317@@ -1023,8 +1064,8 @@ tzparse(const char *name, struct state *
318 /*
319 * Two transitions per year, from EPOCH_YEAR forward.
320 */
321- init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
322- init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
323+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
324+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
325 sp->defaulttype = 0;
326 timecnt = 0;
327 janfirst = 0;
328@@ -1073,19 +1114,15 @@ tzparse(const char *name, struct state *
329 if (!increment_overflow_time
330 (&sp->ats[timecnt],
331 janoffset + starttime))
332- sp->types[timecnt++] = reversed;
333- else if (janoffset)
334- sp->defaulttype = reversed;
335+ sp->types[timecnt++] = !reversed;
336 sp->ats[timecnt] = janfirst;
337 if (!increment_overflow_time
338 (&sp->ats[timecnt],
339 janoffset + endtime))
340 {
341- sp->types[timecnt++] = !reversed;
342+ sp->types[timecnt++] = reversed;
343 yearlim = year + YEARSPERREPEAT + 1;
344 }
345- else if (janoffset)
346- sp->defaulttype = !reversed;
347 }
348 if (increment_overflow_time
349 (&janfirst, janoffset + yearsecs))
350@@ -1094,7 +1131,10 @@ tzparse(const char *name, struct state *
351 }
352 sp->timecnt = timecnt;
353 if (!timecnt)
354+ {
355+ sp->ttis[0] = sp->ttis[1];
356 sp->typecnt = 1; /* Perpetual DST. */
357+ }
358 else if (YEARSPERREPEAT < year - yearbeg)
359 sp->goback = sp->goahead = true;
360 }
361@@ -1163,7 +1203,6 @@ tzparse(const char *name, struct state *
362 * otherwise, add the standard time offset to the
363 * transition time.
364 */
365-
366 /*
367 * Transitions from DST to DDST will effectively disappear
368 * since POSIX provides for only one DST offset.
369@@ -1217,7 +1256,7 @@ tzparse(const char *name, struct state *
370 }
371
372 static void
373-gmtload(struct state *sp)
374+gmtload(struct state *const sp)
375 {
376 if (tzload(gmt, NULL, sp, true) != 0)
377 tzparse(gmt, sp, true);
378@@ -1232,7 +1271,7 @@ gmtload(struct state *sp)
379 */
380 static struct pg_tm *
381 localsub(struct state const *sp, pg_time_t const *timep,
382- struct pg_tm *tmp)
383+ struct pg_tm *const tmp)
384 {
385 const struct ttinfo *ttisp;
386 int i;
387@@ -1300,6 +1339,11 @@ localsub(struct state const *sp, pg_time
388 }
389 ttisp = &sp->ttis[i];
390
391+ /*
392+ * To get (wrong) behavior that's compatible with System V Release 2.0
393+ * you'd replace the statement below with t += ttisp->tt_gmtoff;
394+ * timesub(&t, 0L, sp, tmp);
395+ */
396 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
397 if (result)
398 {
399@@ -1322,8 +1366,10 @@ pg_localtime(const pg_time_t *timep, con
400 *
401 * Except we have a private "struct state" for GMT, so no sp is passed in.
402 */
403+
404 static struct pg_tm *
405-gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
406+gmtsub(pg_time_t const *timep, int32 offset,
407+ struct pg_tm *tmp)
408 {
409 struct pg_tm *result;
410
411@@ -1337,6 +1383,7 @@ gmtsub(pg_time_t const *timep, int32 off
412 gmt_is_set = true;
413 gmtload(gmtptr);
414 }
415+
416 result = timesub(timep, offset, gmtptr, tmp);
417
418 /*
419@@ -1361,6 +1408,7 @@ pg_gmtime(const pg_time_t *timep)
420 * Return the number of leap years through the end of the given year
421 * where, to make the math easy, the answer for year zero is defined as zero.
422 */
423+
424 static int
425 leaps_thru_end_of_nonneg(int y)
426 {
427Index: postgresql-10.5/src/timezone/pgtz.h
428===================================================================
429--- postgresql-10.5.orig/src/timezone/pgtz.h
430+++ postgresql-10.5/src/timezone/pgtz.h
431@@ -49,10 +49,16 @@ struct state
432 pg_time_t ats[TZ_MAX_TIMES];
433 unsigned char types[TZ_MAX_TIMES];
434 struct ttinfo ttis[TZ_MAX_TYPES];
435- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ),
436+ char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 4 /* sizeof gmt */ ),
437 (2 * (TZ_STRLEN_MAX + 1)))];
438 struct lsinfo lsis[TZ_MAX_LEAPS];
439- int defaulttype; /* for early times or if no transitions */
440+
441+ /*
442+ * The time type to use for early times or if no transitions. It is always
443+ * zero for recent tzdb releases. It might be nonzero for data from tzdb
444+ * 2018e or earlier.
445+ */
446+ int defaulttype;
447 };
448
449
450Index: postgresql-10.5/src/timezone/private.h
451===================================================================
452--- postgresql-10.5.orig/src/timezone/private.h
453+++ postgresql-10.5/src/timezone/private.h
454@@ -1,4 +1,7 @@
455+/* Private header for tzdb code. */
456+
457 #ifndef PRIVATE_H
458+
459 #define PRIVATE_H
460
461 /*
462Index: postgresql-10.5/src/timezone/strftime.c
463===================================================================
464--- postgresql-10.5.orig/src/timezone/strftime.c
465+++ postgresql-10.5/src/timezone/strftime.c
466@@ -1,4 +1,4 @@
467-/* Convert a broken-down timestamp to a string. */
468+/* Convert a broken-down timestamp to a string. */
469
470 /*
471 * Copyright 1989 The Regents of the University of California.
472@@ -115,7 +115,7 @@ static char *_add(const char *, char *,
473 static char *_conv(int, const char *, char *, const char *);
474 static char *_fmt(const char *, const struct pg_tm *, char *, const char *,
475 enum warn *);
476-static char *_yconv(int, int, bool, bool, char *, const char *);
477+static char *_yconv(int, int, bool, bool, char *, char const *);
478
479
480 size_t
481@@ -441,7 +441,8 @@ _fmt(const char *format, const struct pg
482
483 /*
484 * C99 and later say that %Z must be replaced by the empty
485- * string if the time zone is not determinable.
486+ * string if the time zone abbreviation is not
487+ * determinable.
488 */
489 continue;
490 case 'z':
491@@ -519,6 +520,7 @@ _add(const char *str, char *pt, const ch
492 * same output as %Y, and that %Y contains at least 4 bytes,
493 * with more only if necessary.
494 */
495+
496 static char *
497 _yconv(int a, int b, bool convert_top, bool convert_yy,
498 char *pt, const char *ptlim)
499@@ -526,7 +528,7 @@ _yconv(int a, int b, bool convert_top, b
500 int lead;
501 int trail;
502
503-#define DIVISOR 100
504+#define DIVISOR 100
505 trail = a % DIVISOR + b % DIVISOR;
506 lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
507 trail %= DIVISOR;
508Index: postgresql-10.5/src/timezone/tzfile.h
509===================================================================
510--- postgresql-10.5.orig/src/timezone/tzfile.h
511+++ postgresql-10.5/src/timezone/tzfile.h
512@@ -1,4 +1,7 @@
513+/* Layout and location of TZif files. */
514+
515 #ifndef TZFILE_H
516+
517 #define TZFILE_H
518
519 /*
520@@ -21,14 +24,14 @@
521 * Information about time zone files.
522 */
523
524-#define TZDEFAULT "localtime"
525+#define TZDEFAULT "/etc/localtime"
526 #define TZDEFRULES "posixrules"
527
528 /*
529 * Each file begins with. . .
530 */
531
532-#define TZ_MAGIC "TZif"
533+#define TZ_MAGIC "TZif"
534
535 struct tzhead
536 {
537Index: postgresql-10.5/src/timezone/zic.c
538===================================================================
539--- postgresql-10.5.orig/src/timezone/zic.c
540+++ postgresql-10.5/src/timezone/zic.c
541@@ -1,3 +1,5 @@
542+/* Compile .zi time zone data into TZif binary files. */
543+
544 /*
545 * This file is in the public domain, so clarified as of
546 * 2006-07-17 by Arthur David Olson.
547@@ -130,8 +132,7 @@ static void adjleap(void);
548 static void associate(void);
549 static void dolink(const char *, const char *, bool);
550 static char **getfields(char *buf);
551-static zic_t gethms(const char *string, const char *errstring,
552- bool);
553+static zic_t gethms(const char *string, const char *errstring);
554 static zic_t getstdoff(char *, bool *);
555 static void infile(const char *filename);
556 static void inleap(char **fields, int nfields);
557@@ -162,7 +163,7 @@ enum
558 PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
559
560 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
561- tz binary files whose POSIX-TZ-style strings contain '<'; see
562+ TZif files whose POSIX-TZ-style strings contain '<'; see
563 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
564 workaround will no longer be needed when Qt 5.6.1 and earlier are
565 obsolete, say in the year 2021. */
566@@ -211,7 +212,7 @@ static int typecnt;
567 #define ZF_RULE 3
568 #define ZF_FORMAT 4
569 #define ZF_TILYEAR 5
570-#define ZF_TILMONTH 6
571+#define ZF_TILMONTH 6
572 #define ZF_TILDAY 7
573 #define ZF_TILTIME 8
574 #define ZONE_MINFIELDS 5
575@@ -224,12 +225,12 @@ static int typecnt;
576 #define ZFC_GMTOFF 0
577 #define ZFC_RULE 1
578 #define ZFC_FORMAT 2
579-#define ZFC_TILYEAR 3
580+#define ZFC_TILYEAR 3
581 #define ZFC_TILMONTH 4
582 #define ZFC_TILDAY 5
583-#define ZFC_TILTIME 6
584-#define ZONEC_MINFIELDS 3
585-#define ZONEC_MAXFIELDS 7
586+#define ZFC_TILTIME 6
587+#define ZONEC_MINFIELDS 3
588+#define ZONEC_MAXFIELDS 7
589
590 /*
591 * Which files are which on a Rule line.
592@@ -244,7 +245,7 @@ static int typecnt;
593 #define RF_TOD 7
594 #define RF_STDOFF 8
595 #define RF_ABBRVAR 9
596-#define RULE_FIELDS 10
597+#define RULE_FIELDS 10
598
599 /*
600 * Which fields are which on a Link line.
601@@ -252,7 +253,7 @@ static int typecnt;
602
603 #define LF_FROM 1
604 #define LF_TO 2
605-#define LINK_FIELDS 3
606+#define LINK_FIELDS 3
607
608 /*
609 * Which fields are which on a Leap line.
610@@ -264,7 +265,7 @@ static int typecnt;
611 #define LP_TIME 4
612 #define LP_CORR 5
613 #define LP_ROLL 6
614-#define LEAP_FIELDS 7
615+#define LEAP_FIELDS 7
616
617 /*
618 * Year synonyms.
619@@ -998,48 +999,6 @@ dolink(char const *fromfield, char const
620 static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
621 static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
622
623-/*
624- * Estimated time of the Big Bang, in seconds since the POSIX epoch.
625- * rounded downward to the negation of a power of two that is
626- * comfortably outside the error bounds.
627- *
628- * For the time of the Big Bang, see:
629- *
630- * Ade PAR, Aghanim N, Armitage-Caplan C et al. Planck 2013 results.
631- * I. Overview of products and scientific results.
632- * arXiv:1303.5062 2013-03-20 20:10:01 UTC
633- * <https://arxiv.org/pdf/1303.5062v1> [PDF]
634- *
635- * Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits
636- * gives the value 13.798 plus-or-minus 0.037 billion years.
637- * Multiplying this by 1000000000 and then by 31557600 (the number of
638- * seconds in an astronomical year) gives a value that is comfortably
639- * less than 2**59, so BIG_BANG is - 2**59.
640- *
641- * BIG_BANG is approximate, and may change in future versions.
642- * Please do not rely on its exact value.
643- */
644-
645-#ifndef BIG_BANG
646-#define BIG_BANG (- (((zic_t) 1) << 59))
647-#endif
648-
649-/* If true, work around GNOME bug 730332
650- <https://bugzilla.gnome.org/show_bug.cgi?id=730332>
651- by refusing to output time stamps before BIG_BANG.
652- Such time stamps are physically suspect anyway.
653-
654- The GNOME bug is scheduled to be fixed in GNOME 3.22, and if so
655- this workaround will no longer be needed when GNOME 3.21 and
656- earlier are obsolete, say in the year 2021. */
657-enum
658-{
659-WORK_AROUND_GNOME_BUG_730332 = true};
660-
661-static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
662- ? BIG_BANG
663- : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
664-
665 /* Return true if NAME is a directory. */
666 static bool
667 itsdir(char const *name)
668@@ -1281,8 +1240,9 @@ infile(const char *name)
669 * A null string maps to zero.
670 * Call error with errstring and return zero on errors.
671 */
672+
673 static zic_t
674-gethms(char const *string, char const *errstring, bool signable)
675+gethms(char const *string, char const *errstring)
676 {
677 /* PG: make hh be int not zic_t to avoid sscanf portability issues */
678 int hh;
679@@ -1299,9 +1259,7 @@ gethms(char const *string, char const *e
680
681 if (string == NULL || *string == '\0')
682 return 0;
683- if (!signable)
684- sign = 1;
685- else if (*string == '-')
686+ if (*string == '-')
687 {
688 sign = -1;
689 ++string;
690@@ -1384,7 +1342,7 @@ getstdoff(char *field, bool *isdst)
691 break;
692 }
693 }
694- stdoff = gethms(field, _("invalid saved time"), true);
695+ stdoff = gethms(field, _("invalid saved time"));
696 *isdst = dst < 0 ? stdoff != 0 : dst;
697 return stdoff;
698 }
699@@ -1399,10 +1357,29 @@ inrule(char **fields, int nfields)
700 error(_("wrong number of fields on Rule line"));
701 return;
702 }
703- if (*fields[RF_NAME] == '\0')
704+ switch (*fields[RF_NAME])
705 {
706- error(_("nameless rule"));
707- return;
708+ case '\0':
709+ case ' ':
710+ case '\f':
711+ case '\n':
712+ case '\r':
713+ case '\t':
714+ case '\v':
715+ case '+':
716+ case '-':
717+ case '0':
718+ case '1':
719+ case '2':
720+ case '3':
721+ case '4':
722+ case '5':
723+ case '6':
724+ case '7':
725+ case '8':
726+ case '9':
727+ error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
728+ return;
729 }
730 r.r_filename = filename;
731 r.r_linenum = linenum;
732@@ -1507,7 +1484,7 @@ inzsub(char **fields, int nfields, bool
733 }
734 z.z_filename = filename;
735 z.z_linenum = linenum;
736- z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), true);
737+ z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));
738 if ((cp = strchr(fields[i_format], '%')) != NULL)
739 {
740 if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
741@@ -1649,7 +1626,7 @@ inleap(char **fields, int nfields)
742 return;
743 }
744 t = dayoff * SECSPERDAY;
745- tod = gethms(fields[LP_TIME], _("invalid time of day"), false);
746+ tod = gethms(fields[LP_TIME], _("invalid time of day"));
747 cp = fields[LP_CORR];
748 {
749 bool positive;
750@@ -1757,7 +1734,7 @@ rulesub(struct rule *rp, const char *loy
751 break;
752 }
753 }
754- rp->r_tod = gethms(dp, _("invalid time of day"), false);
755+ rp->r_tod = gethms(dp, _("invalid time of day"));
756 free(dp);
757
758 /*
759@@ -1942,7 +1919,43 @@ is32(const zic_t x)
760 }
761
762 static void
763-writezone(const char *const name, const char *const string, char version)
764+swaptypes(int i, int j)
765+{
766+ {
767+ zic_t t = gmtoffs[i];
768+
769+ gmtoffs[i] = gmtoffs[j];
770+ gmtoffs[j] = t;
771+ }
772+ {
773+ char t = isdsts[i];
774+
775+ isdsts[i] = isdsts[j];
776+ isdsts[j] = t;
777+ }
778+ {
779+ unsigned char t = abbrinds[i];
780+
781+ abbrinds[i] = abbrinds[j];
782+ abbrinds[j] = t;
783+ }
784+ {
785+ bool t = ttisstds[i];
786+
787+ ttisstds[i] = ttisstds[j];
788+ ttisstds[j] = t;
789+ }
790+ {
791+ bool t = ttisgmts[i];
792+
793+ ttisgmts[i] = ttisgmts[j];
794+ ttisgmts[j] = t;
795+ }
796+}
797+
798+static void
799+writezone(const char *const name, const char *const string, char version,
800+ int defaulttype)
801 {
802 FILE *fp;
803 ptrdiff_t i,
804@@ -1977,14 +1990,12 @@ writezone(const char *const name, const
805
806 toi = 0;
807 fromi = 0;
808- while (fromi < timecnt && attypes[fromi].at < early_time)
809- ++fromi;
810 for (; fromi < timecnt; ++fromi)
811 {
812- if (toi > 1 && ((attypes[fromi].at +
813- gmtoffs[attypes[toi - 1].type]) <=
814- (attypes[toi - 1].at +
815- gmtoffs[attypes[toi - 2].type])))
816+ if (toi != 0 && ((attypes[fromi].at +
817+ gmtoffs[attypes[toi - 1].type]) <=
818+ (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
819+ : attypes[toi - 2].type])))
820 {
821 attypes[toi - 1].type =
822 attypes[fromi].type;
823@@ -2019,8 +2030,8 @@ writezone(const char *const name, const
824 }
825
826 /*
827- * Work around QTBUG-53071 for time stamps less than y2038_boundary - 1,
828- * by inserting a no-op transition at time y2038_boundary - 1. This works
829+ * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
830+ * inserting a no-op transition at time y2038_boundary - 1. This works
831 * only for timestamps before the boundary, which should be good enough in
832 * practice as QTBUG-53071 should be long-dead by 2038.
833 */
834@@ -2116,7 +2127,8 @@ writezone(const char *const name, const
835 int thisleapi,
836 thisleapcnt,
837 thisleaplim;
838- int writetype[TZ_MAX_TYPES];
839+ int old0;
840+ char omittype[TZ_MAX_TYPES];
841 int typemap[TZ_MAX_TYPES];
842 int thistypecnt;
843 char thischars[TZ_MAX_CHARS];
844@@ -2144,28 +2156,19 @@ writezone(const char *const name, const
845 error(_("too many transition times"));
846 thistimelim = thistimei + thistimecnt;
847 thisleaplim = thisleapi + thisleapcnt;
848- for (i = 0; i < typecnt; ++i)
849- writetype[i] = thistimecnt == timecnt;
850- if (thistimecnt == 0)
851- {
852- /*
853- * No transition times fall in the current (32- or 64-bit) window.
854- */
855- if (typecnt != 0)
856- writetype[typecnt - 1] = true;
857- }
858- else
859- {
860- for (i = thistimei - 1; i < thistimelim; ++i)
861- if (i >= 0)
862- writetype[types[i]] = true;
863+ memset(omittype, true, typecnt);
864+ omittype[defaulttype] = false;
865+ for (i = thistimei; i < thistimelim; i++)
866+ omittype[types[i]] = false;
867+
868+ /*
869+ * Reorder types to make DEFAULTTYPE type 0. Use TYPEMAP to swap OLD0
870+ * and DEFAULTTYPE so that DEFAULTTYPE appears as type 0 in the output
871+ * instead of OLD0. TYPEMAP also omits unused types.
872+ */
873+ old0 = strlen(omittype);
874+ swaptypes(old0, defaulttype);
875
876- /*
877- * For America/Godthab and Antarctica/Palmer
878- */
879- if (thistimei == 0)
880- writetype[0] = true;
881- }
882 #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
883
884 /*
885@@ -2187,8 +2190,8 @@ writezone(const char *const name, const
886 mrudst = types[i];
887 else
888 mrustd = types[i];
889- for (i = 0; i < typecnt; ++i)
890- if (writetype[i])
891+ for (i = old0; i < typecnt; i++)
892+ if (!omittype[i])
893 {
894 if (isdsts[i])
895 hidst = i;
896@@ -2205,7 +2208,7 @@ writezone(const char *const name, const
897 ttisstds[mrudst],
898 ttisgmts[mrudst]);
899 isdsts[mrudst] = 1;
900- writetype[type] = true;
901+ omittype[type] = false;
902 }
903 if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
904 gmtoffs[histd] != gmtoffs[mrustd])
905@@ -2217,22 +2220,26 @@ writezone(const char *const name, const
906 ttisstds[mrustd],
907 ttisgmts[mrustd]);
908 isdsts[mrustd] = 0;
909- writetype[type] = true;
910+ omittype[type] = false;
911 }
912 }
913 #endif /* !defined
914 * LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
915 thistypecnt = 0;
916- for (i = 0; i < typecnt; ++i)
917- typemap[i] = writetype[i] ? thistypecnt++ : -1;
918+ for (i = old0; i < typecnt; i++)
919+ if (!omittype[i])
920+ typemap[i == old0 ? defaulttype
921+ : i == defaulttype ? old0 : i]
922+ = thistypecnt++;
923+
924 for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
925 indmap[i] = -1;
926 thischarcnt = 0;
927- for (i = 0; i < typecnt; ++i)
928+ for (i = old0; i < typecnt; i++)
929 {
930 char *thisabbr;
931
932- if (!writetype[i])
933+ if (omittype[i])
934 continue;
935 if (indmap[abbrinds[i]] >= 0)
936 continue;
937@@ -2267,23 +2274,16 @@ writezone(const char *const name, const
938 DO(tzh_typecnt);
939 DO(tzh_charcnt);
940 #undef DO
941- for (i = thistimei; i < thistimelim; ++i)
942- if (pass == 1)
943
944- /*
945- * Output an INT32_MIN "transition" if appropriate; see above.
946- */
947- puttzcode(((ats[i] < PG_INT32_MIN) ?
948- PG_INT32_MIN : ats[i]), fp);
949- else
950+ /* PG: print current timezone abbreviations if requested */
951+ if (print_abbrevs && pass == 2)
952+ {
953+ /* Print "type" data for periods ending after print_cutoff */
954+ for (i = thistimei; i < thistimelim; ++i)
955 {
956- puttzcode64(ats[i], fp);
957-
958- /* Print current timezone abbreviations if requested */
959- if (print_abbrevs &&
960- (i == thistimelim - 1 || ats[i + 1] > print_cutoff))
961+ if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
962 {
963- unsigned char tm = typemap[types[i]];
964+ unsigned char tm = types[i];
965 char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
966
967 /* filter out assorted junk entries */
968@@ -2295,6 +2295,32 @@ writezone(const char *const name, const
969 isdsts[tm] ? "\tD" : "");
970 }
971 }
972+ /* Print the default type if we have no transitions at all */
973+ if (thistimei >= thistimelim)
974+ {
975+ unsigned char tm = defaulttype;
976+ char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
977+
978+ /* filter out assorted junk entries */
979+ if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
980+ strcmp(thisabbrev, "zzz") != 0)
981+ fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
982+ thisabbrev,
983+ gmtoffs[tm],
984+ isdsts[tm] ? "\tD" : "");
985+ }
986+ }
987+
988+ for (i = thistimei; i < thistimelim; ++i)
989+ if (pass == 1)
990+
991+ /*
992+ * Output an INT32_MIN "transition" if appropriate; see above.
993+ */
994+ puttzcode(((ats[i] < PG_INT32_MIN) ?
995+ PG_INT32_MIN : ats[i]), fp);
996+ else
997+ puttzcode64(ats[i], fp);
998 for (i = thistimei; i < thistimelim; ++i)
999 {
1000 unsigned char uc;
1001@@ -2302,8 +2328,8 @@ writezone(const char *const name, const
1002 uc = typemap[types[i]];
1003 fwrite(&uc, sizeof uc, 1, fp);
1004 }
1005- for (i = 0; i < typecnt; ++i)
1006- if (writetype[i])
1007+ for (i = old0; i < typecnt; i++)
1008+ if (!omittype[i])
1009 {
1010 puttzcode(gmtoffs[i], fp);
1011 putc(isdsts[i], fp);
1012@@ -2346,12 +2372,13 @@ writezone(const char *const name, const
1013 puttzcode64(todo, fp);
1014 puttzcode(corr[i], fp);
1015 }
1016- for (i = 0; i < typecnt; ++i)
1017- if (writetype[i])
1018+ for (i = old0; i < typecnt; i++)
1019+ if (!omittype[i])
1020 putc(ttisstds[i], fp);
1021- for (i = 0; i < typecnt; ++i)
1022- if (writetype[i])
1023+ for (i = old0; i < typecnt; i++)
1024+ if (!omittype[i])
1025 putc(ttisgmts[i], fp);
1026+ swaptypes(old0, defaulttype);
1027 }
1028 fprintf(fp, "\n%s\n", string);
1029 close_file(fp, directory, name);
1030@@ -2757,6 +2784,7 @@ outzone(const struct zone *zpfirst, ptrd
1031 zic_t one = 1;
1032 zic_t y2038_boundary = one << 31;
1033 zic_t max_year0;
1034+ int defaulttype = -1;
1035
1036 max_abbr_len = 2 + max_format_len + max_abbrvar_len;
1037 max_envvar_len = 2 * max_abbr_len + 5 * 9;
1038@@ -2880,9 +2908,9 @@ outzone(const struct zone *zpfirst, ptrd
1039 */
1040 stdoff = 0;
1041 zp = &zpfirst[i];
1042- usestart = i > 0 && (zp - 1)->z_untiltime > early_time;
1043+ usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
1044 useuntil = i < (zonecount - 1);
1045- if (useuntil && zp->z_untiltime <= early_time)
1046+ if (useuntil && zp->z_untiltime <= min_time)
1047 continue;
1048 gmtoff = zp->z_gmtoff;
1049 eat(zp->z_filename, zp->z_linenum);
1050@@ -2901,7 +2929,7 @@ outzone(const struct zone *zpfirst, ptrd
1051 usestart = false;
1052 }
1053 else
1054- addtt(early_time, type);
1055+ defaulttype = type;
1056 }
1057 else
1058 for (year = min_year; year <= max_year; ++year)
1059@@ -3032,6 +3060,8 @@ outzone(const struct zone *zpfirst, ptrd
1060 offset = oadd(zp->z_gmtoff, rp->r_stdoff);
1061 type = addtype(offset, ab, rp->r_isdst,
1062 rp->r_todisstd, rp->r_todisgmt);
1063+ if (defaulttype < 0 && !rp->r_isdst)
1064+ defaulttype = type;
1065 if (rp->r_hiyear == ZIC_MAX
1066 && !(0 <= lastatmax
1067 && ktime < attypes[lastatmax].at))
1068@@ -3050,11 +3080,15 @@ outzone(const struct zone *zpfirst, ptrd
1069 if (*startbuf == '\0')
1070 error(_("cannot determine time zone abbreviation to use just after until time"));
1071 else
1072- addtt(starttime,
1073- addtype(startoff, startbuf,
1074- startoff != zp->z_gmtoff,
1075- startttisstd,
1076- startttisgmt));
1077+ {
1078+ bool isdst = startoff != zp->z_gmtoff;
1079+
1080+ type = addtype(startoff, startbuf, isdst,
1081+ startttisstd, startttisgmt);
1082+ if (defaulttype < 0 && !isdst)
1083+ defaulttype = type;
1084+ addtt(starttime, type);
1085+ }
1086 }
1087
1088 /*
1089@@ -3071,6 +3105,8 @@ outzone(const struct zone *zpfirst, ptrd
1090 starttime = tadd(starttime, -gmtoff);
1091 }
1092 }
1093+ if (defaulttype < 0)
1094+ defaulttype = 0;
1095 if (0 <= lastatmax)
1096 attypes[lastatmax].dontmerge = true;
1097 if (do_extend)
1098@@ -3100,7 +3136,7 @@ outzone(const struct zone *zpfirst, ptrd
1099 attypes[timecnt - 1].dontmerge = true;
1100 }
1101 }
1102- writezone(zpfirst->z_name, envvar, version);
1103+ writezone(zpfirst->z_name, envvar, version, defaulttype);
1104 free(startbuf);
1105 free(ab);
1106 free(envvar);
1107@@ -3109,21 +3145,6 @@ outzone(const struct zone *zpfirst, ptrd
1108 static void
1109 addtt(zic_t starttime, int type)
1110 {
1111- if (starttime <= early_time
1112- || (timecnt == 1 && attypes[0].at < early_time))
1113- {
1114- gmtoffs[0] = gmtoffs[type];
1115- isdsts[0] = isdsts[type];
1116- ttisstds[0] = ttisstds[type];
1117- ttisgmts[0] = ttisgmts[type];
1118- if (abbrinds[type] != 0)
1119- strcpy(chars, &chars[abbrinds[type]]);
1120- abbrinds[0] = 0;
1121- charcnt = strlen(chars) + 1;
1122- typecnt = 1;
1123- timecnt = 0;
1124- type = 0;
1125- }
1126 attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
1127 attypes[timecnt].at = starttime;
1128 attypes[timecnt].dontmerge = false;
1129@@ -3361,7 +3382,7 @@ is_alpha(char a)
1130 }
1131
1132 /* If A is an uppercase character in the C locale, return its lowercase
1133- * counterpart. Otherwise, return A. */
1134+ counterpart. Otherwise, return A. */
1135 static char
1136 lowerit(char a)
1137 {
1138@@ -3628,6 +3649,18 @@ rpytime(const struct rule *rp, zic_t wan
1139 dayoff = 0;
1140 m = TM_JANUARY;
1141 y = EPOCH_YEAR;
1142+ if (y < wantedy)
1143+ {
1144+ wantedy -= y;
1145+ dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
1146+ wantedy %= YEARSPERREPEAT;
1147+ wantedy += y;
1148+ }
1149+ else if (wantedy < 0)
1150+ {
1151+ dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
1152+ wantedy %= YEARSPERREPEAT;
1153+ }
1154 while (wantedy != y)
1155 {
1156 if (wantedy > y)
1157@@ -3706,7 +3739,6 @@ will not work with pre-2004 versions of
1158 if (dayoff > max_time / SECSPERDAY)
1159 return max_time;
1160 t = (zic_t) dayoff * SECSPERDAY;
1161-
1162 return tadd(t, rp->r_tod);
1163 }
1164