1
+ /* Convert timestamp from pg_time_t to struct pg_tm. */
2
+
1
3
/*
2
4
* This file is in the public domain, so clarified as of
3
5
* 1996-06-05 by Arthur David Olson.
@@ -117,7 +119,7 @@ init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
117
119
}
118
120
119
121
static int32
120
- detzcode (const char * codep )
122
+ detzcode (const char * const codep )
121
123
{
122
124
int32 result ;
123
125
int i ;
@@ -143,7 +145,7 @@ detzcode(const char *codep)
143
145
}
144
146
145
147
static int64
146
- detzcode64 (const char * codep )
148
+ detzcode64 (const char * const codep )
147
149
{
148
150
uint64 result ;
149
151
int i ;
@@ -258,8 +260,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
258
260
int32 charcnt = detzcode (up -> tzhead .tzh_charcnt );
259
261
char const * p = up -> buf + tzheadsize ;
260
262
263
+ /*
264
+ * Although tzfile(5) currently requires typecnt to be nonzero,
265
+ * support future formats that may allow zero typecnt in files that
266
+ * have a TZ string and no transitions.
267
+ */
261
268
if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
262
- && 0 < typecnt && typecnt < TZ_MAX_TYPES
269
+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
263
270
&& 0 <= timecnt && timecnt < TZ_MAX_TIMES
264
271
&& 0 <= charcnt && charcnt < TZ_MAX_CHARS
265
272
&& (ttisstdcnt == typecnt || ttisstdcnt == 0 )
@@ -416,8 +423,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
416
423
struct state * ts = & lsp -> u .st ;
417
424
418
425
up -> buf [nread - 1 ] = '\0' ;
419
- if (tzparse (& up -> buf [1 ], ts , false)
420
- && ts -> typecnt == 2 )
426
+ if (tzparse (& up -> buf [1 ], ts , false))
421
427
{
422
428
/*
423
429
* Attempt to reuse existing abbreviations. Without this,
@@ -430,7 +436,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
430
436
int gotabbr = 0 ;
431
437
int charcnt = sp -> charcnt ;
432
438
433
- for (i = 0 ; i < 2 ; i ++ )
439
+ for (i = 0 ; i < ts -> typecnt ; i ++ )
434
440
{
435
441
char * tsabbr = ts -> chars + ts -> ttis [i ].tt_abbrind ;
436
442
int j ;
@@ -455,7 +461,7 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
455
461
}
456
462
}
457
463
}
458
- if (gotabbr == 2 )
464
+ if (gotabbr == ts -> typecnt )
459
465
{
460
466
sp -> charcnt = charcnt ;
461
467
@@ -470,7 +476,8 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
470
476
sp -> timecnt -- ;
471
477
472
478
for (i = 0 ; i < ts -> timecnt ; i ++ )
473
- if (sp -> ats [sp -> timecnt - 1 ] < ts -> ats [i ])
479
+ if (sp -> timecnt == 0
480
+ || sp -> ats [sp -> timecnt - 1 ] < ts -> ats [i ])
474
481
break ;
475
482
while (i < ts -> timecnt
476
483
&& sp -> timecnt < TZ_MAX_TIMES )
@@ -481,11 +488,13 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
481
488
sp -> timecnt ++ ;
482
489
i ++ ;
483
490
}
484
- sp -> ttis [ sp -> typecnt ++ ] = ts -> ttis [ 0 ];
485
- sp -> ttis [sp -> typecnt ++ ] = ts -> ttis [1 ];
491
+ for ( i = 0 ; i < ts -> typecnt ; i ++ )
492
+ sp -> ttis [sp -> typecnt ++ ] = ts -> ttis [i ];
486
493
}
487
494
}
488
495
}
496
+ if (sp -> typecnt == 0 )
497
+ return EINVAL ;
489
498
if (sp -> timecnt > 1 )
490
499
{
491
500
for (i = 1 ; i < sp -> timecnt ; ++ i )
@@ -506,6 +515,18 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
506
515
}
507
516
}
508
517
518
+ /*
519
+ * Infer sp->defaulttype from the data. Although this default type is
520
+ * always zero for data from recent tzdb releases, things are trickier for
521
+ * data from tzdb 2018e or earlier.
522
+ *
523
+ * The first set of heuristics work around bugs in 32-bit data generated
524
+ * by tzdb 2013c or earlier. The workaround is for zones like
525
+ * Australia/Macquarie where timestamps before the first transition have a
526
+ * time type that is not the earliest standard-time type. See:
527
+ * https://mm.icann.org/pipermail/tz/2013-May/019368.html
528
+ */
529
+
509
530
/*
510
531
* If type 0 is unused in transitions, it's the type to use for early
511
532
* times.
@@ -528,6 +549,11 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
528
549
break ;
529
550
}
530
551
552
+ /*
553
+ * The next heuristics are for data generated by tzdb 2018e or earlier,
554
+ * for zones like EST5EDT where the first transition is to DST.
555
+ */
556
+
531
557
/*
532
558
* If no result yet, find the first standard type. If there is none, punt
533
559
* to type zero.
@@ -542,7 +568,14 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
542
568
break ;
543
569
}
544
570
}
571
+
572
+ /*
573
+ * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
574
+ * worry about 2018e-or-earlier data. Even simpler would be to remove the
575
+ * defaulttype member and just use 0 in its place.
576
+ */
545
577
sp -> defaulttype = i ;
578
+
546
579
return 0 ;
547
580
}
548
581
@@ -601,10 +634,11 @@ static const int year_lengths[2] = {
601
634
};
602
635
603
636
/*
604
- * Given a pointer into a time zone string, scan until a character that is not
605
- * a valid character in a zone name is found. Return a pointer to that
606
- * character.
637
+ * Given a pointer into a timezone string, scan until a character that is not
638
+ * a valid character in a time zone abbreviation is found.
639
+ * Return a pointer to that character.
607
640
*/
641
+
608
642
static const char *
609
643
getzname (const char * strp )
610
644
{
@@ -617,15 +651,17 @@ getzname(const char *strp)
617
651
}
618
652
619
653
/*
620
- * Given a pointer into an extended time zone string, scan until the ending
621
- * delimiter of the zone name is located. Return a pointer to the delimiter.
654
+ * Given a pointer into an extended timezone string, scan until the ending
655
+ * delimiter of the time zone abbreviation is located.
656
+ * Return a pointer to the delimiter.
622
657
*
623
658
* As with getzname above, the legal character set is actually quite
624
659
* restricted, with other characters producing undefined results.
625
660
* We don't do any checking here; checking is done later in common-case code.
626
661
*/
662
+
627
663
static const char *
628
- getqzname (const char * strp , int delim )
664
+ getqzname (const char * strp , const int delim )
629
665
{
630
666
int c ;
631
667
@@ -635,13 +671,14 @@ getqzname(const char *strp, int delim)
635
671
}
636
672
637
673
/*
638
- * Given a pointer into a time zone string, extract a number from that string.
674
+ * Given a pointer into a timezone string, extract a number from that string.
639
675
* Check that the number is within a specified range; if it is not, return
640
676
* NULL.
641
677
* Otherwise, return a pointer to the first character not part of the number.
642
678
*/
679
+
643
680
static const char *
644
- getnum (const char * strp , int * nump , int min , int max )
681
+ getnum (const char * strp , int * const nump , const int min , const int max )
645
682
{
646
683
char c ;
647
684
int num ;
@@ -663,14 +700,15 @@ getnum(const char *strp, int *nump, int min, int max)
663
700
}
664
701
665
702
/*
666
- * Given a pointer into a time zone string, extract a number of seconds,
703
+ * Given a pointer into a timezone string, extract a number of seconds,
667
704
* in hh[:mm[:ss]] form, from the string.
668
705
* If any error occurs, return NULL.
669
706
* Otherwise, return a pointer to the first character not part of the number
670
707
* of seconds.
671
708
*/
709
+
672
710
static const char *
673
- getsecs (const char * strp , int32 * secsp )
711
+ getsecs (const char * strp , int32 * const secsp )
674
712
{
675
713
int num ;
676
714
@@ -704,13 +742,14 @@ getsecs(const char *strp, int32 *secsp)
704
742
}
705
743
706
744
/*
707
- * Given a pointer into a time zone string, extract an offset, in
745
+ * Given a pointer into a timezone string, extract an offset, in
708
746
* [+-]hh[:mm[:ss]] form, from the string.
709
747
* If any error occurs, return NULL.
710
748
* Otherwise, return a pointer to the first character not part of the time.
711
749
*/
750
+
712
751
static const char *
713
- getoffset (const char * strp , int32 * offsetp )
752
+ getoffset (const char * strp , int32 * const offsetp )
714
753
{
715
754
bool neg = false;
716
755
@@ -730,13 +769,14 @@ getoffset(const char *strp, int32 *offsetp)
730
769
}
731
770
732
771
/*
733
- * Given a pointer into a time zone string, extract a rule in the form
772
+ * Given a pointer into a timezone string, extract a rule in the form
734
773
* date[/time]. See POSIX section 8 for the format of "date" and "time".
735
774
* If a valid rule is not found, return NULL.
736
775
* Otherwise, return a pointer to the first character not part of the rule.
737
776
*/
777
+
738
778
static const char *
739
- getrule (const char * strp , struct rule * rulep )
779
+ getrule (const char * strp , struct rule * const rulep )
740
780
{
741
781
if (* strp == 'J' )
742
782
{
@@ -795,9 +835,10 @@ getrule(const char *strp, struct rule *rulep)
795
835
* Given a year, a rule, and the offset from UT at the time that rule takes
796
836
* effect, calculate the year-relative time that rule takes effect.
797
837
*/
838
+
798
839
static int32
799
- transtime (int year , const struct rule * rulep ,
800
- int32 offset )
840
+ transtime (const int year , const struct rule * const rulep ,
841
+ const int32 offset )
801
842
{
802
843
bool leapyear ;
803
844
int32 value ;
@@ -967,7 +1008,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
967
1008
{
968
1009
dstname = name ;
969
1010
name = getzname (name );
970
- dstlen = name - dstname ; /* length of DST zone name */
1011
+ dstlen = name - dstname ; /* length of DST abbr. */
971
1012
}
972
1013
if (!dstlen )
973
1014
return false;
@@ -1039,8 +1080,8 @@ tzparse(const char *name, struct state *sp, bool lastditch)
1039
1080
/*
1040
1081
* Two transitions per year, from EPOCH_YEAR forward.
1041
1082
*/
1042
- init_ttinfo (& sp -> ttis [0 ], - dstoffset , true, stdlen + 1 );
1043
- init_ttinfo (& sp -> ttis [1 ], - stdoffset , false, 0 );
1083
+ init_ttinfo (& sp -> ttis [0 ], - stdoffset , false, 0 );
1084
+ init_ttinfo (& sp -> ttis [1 ], - dstoffset , true, stdlen + 1 );
1044
1085
sp -> defaulttype = 0 ;
1045
1086
timecnt = 0 ;
1046
1087
janfirst = 0 ;
@@ -1089,19 +1130,15 @@ tzparse(const char *name, struct state *sp, bool lastditch)
1089
1130
if (!increment_overflow_time
1090
1131
(& sp -> ats [timecnt ],
1091
1132
janoffset + starttime ))
1092
- sp -> types [timecnt ++ ] = reversed ;
1093
- else if (janoffset )
1094
- sp -> defaulttype = reversed ;
1133
+ sp -> types [timecnt ++ ] = !reversed ;
1095
1134
sp -> ats [timecnt ] = janfirst ;
1096
1135
if (!increment_overflow_time
1097
1136
(& sp -> ats [timecnt ],
1098
1137
janoffset + endtime ))
1099
1138
{
1100
- sp -> types [timecnt ++ ] = ! reversed ;
1139
+ sp -> types [timecnt ++ ] = reversed ;
1101
1140
yearlim = year + YEARSPERREPEAT + 1 ;
1102
1141
}
1103
- else if (janoffset )
1104
- sp -> defaulttype = !reversed ;
1105
1142
}
1106
1143
if (increment_overflow_time
1107
1144
(& janfirst , janoffset + yearsecs ))
@@ -1110,7 +1147,10 @@ tzparse(const char *name, struct state *sp, bool lastditch)
1110
1147
}
1111
1148
sp -> timecnt = timecnt ;
1112
1149
if (!timecnt )
1150
+ {
1151
+ sp -> ttis [0 ] = sp -> ttis [1 ];
1113
1152
sp -> typecnt = 1 ; /* Perpetual DST. */
1153
+ }
1114
1154
else if (YEARSPERREPEAT < year - yearbeg )
1115
1155
sp -> goback = sp -> goahead = true;
1116
1156
}
@@ -1179,7 +1219,6 @@ tzparse(const char *name, struct state *sp, bool lastditch)
1179
1219
* otherwise, add the standard time offset to the
1180
1220
* transition time.
1181
1221
*/
1182
-
1183
1222
/*
1184
1223
* Transitions from DST to DDST will effectively disappear
1185
1224
* since POSIX provides for only one DST offset.
@@ -1233,7 +1272,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
1233
1272
}
1234
1273
1235
1274
static void
1236
- gmtload (struct state * sp )
1275
+ gmtload (struct state * const sp )
1237
1276
{
1238
1277
if (tzload (gmt , NULL , sp , true) != 0 )
1239
1278
tzparse (gmt , sp , true);
@@ -1248,7 +1287,7 @@ gmtload(struct state *sp)
1248
1287
*/
1249
1288
static struct pg_tm *
1250
1289
localsub (struct state const * sp , pg_time_t const * timep ,
1251
- struct pg_tm * tmp )
1290
+ struct pg_tm * const tmp )
1252
1291
{
1253
1292
const struct ttinfo * ttisp ;
1254
1293
int i ;
@@ -1316,6 +1355,11 @@ localsub(struct state const *sp, pg_time_t const *timep,
1316
1355
}
1317
1356
ttisp = & sp -> ttis [i ];
1318
1357
1358
+ /*
1359
+ * To get (wrong) behavior that's compatible with System V Release 2.0
1360
+ * you'd replace the statement below with t += ttisp->tt_gmtoff;
1361
+ * timesub(&t, 0L, sp, tmp);
1362
+ */
1319
1363
result = timesub (& t , ttisp -> tt_gmtoff , sp , tmp );
1320
1364
if (result )
1321
1365
{
@@ -1338,8 +1382,10 @@ pg_localtime(const pg_time_t *timep, const pg_tz *tz)
1338
1382
*
1339
1383
* Except we have a private "struct state" for GMT, so no sp is passed in.
1340
1384
*/
1385
+
1341
1386
static struct pg_tm *
1342
- gmtsub (pg_time_t const * timep , int32 offset , struct pg_tm * tmp )
1387
+ gmtsub (pg_time_t const * timep , int32 offset ,
1388
+ struct pg_tm * tmp )
1343
1389
{
1344
1390
struct pg_tm * result ;
1345
1391
@@ -1354,6 +1400,7 @@ gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
1354
1400
return NULL ; /* errno should be set by malloc */
1355
1401
gmtload (gmtptr );
1356
1402
}
1403
+
1357
1404
result = timesub (timep , offset , gmtptr , tmp );
1358
1405
1359
1406
/*
@@ -1378,6 +1425,7 @@ pg_gmtime(const pg_time_t *timep)
1378
1425
* Return the number of leap years through the end of the given year
1379
1426
* where, to make the math easy, the answer for year zero is defined as zero.
1380
1427
*/
1428
+
1381
1429
static int
1382
1430
leaps_thru_end_of_nonneg (int y )
1383
1431
{
0 commit comments