17
17
#include <fcntl.h>
18
18
19
19
#include "datatype/timestamp.h"
20
- #include "private.h"
21
20
#include "pgtz.h"
21
+
22
+ #include "private.h"
22
23
#include "tzfile.h"
23
24
24
25
@@ -414,10 +415,10 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
414
415
{
415
416
/*
416
417
* 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
421
422
* example.
422
423
*/
423
424
int gotabbr = 0 ;
@@ -451,6 +452,17 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend,
451
452
if (gotabbr == 2 )
452
453
{
453
454
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
+
454
466
for (i = 0 ; i < ts -> timecnt ; i ++ )
455
467
if (sp -> ats [sp -> timecnt - 1 ] < ts -> ats [i ])
456
468
break ;
@@ -974,6 +986,8 @@ tzparse(const char *name, struct state * sp, bool lastditch)
974
986
int yearlim ;
975
987
int timecnt ;
976
988
pg_time_t janfirst ;
989
+ int32 janoffset = 0 ;
990
+ int yearbeg ;
977
991
978
992
++ name ;
979
993
if ((name = getrule (name , & start )) == NULL )
@@ -994,8 +1008,23 @@ tzparse(const char *name, struct state * sp, bool lastditch)
994
1008
sp -> defaulttype = 0 ;
995
1009
timecnt = 0 ;
996
1010
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 ++ )
999
1028
{
1000
1029
int32
1001
1030
starttime = transtime (year , & start , stdoffset ),
@@ -1020,24 +1049,34 @@ tzparse(const char *name, struct state * sp, bool lastditch)
1020
1049
{
1021
1050
if (TZ_MAX_TIMES - 2 < timecnt )
1022
1051
break ;
1023
- yearlim = year + YEARSPERREPEAT + 1 ;
1024
1052
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 ;
1029
1059
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 ;
1034
1069
}
1035
- if (increment_overflow_time (& janfirst , yearsecs ))
1070
+ if (increment_overflow_time
1071
+ (& janfirst , janoffset + yearsecs ))
1036
1072
break ;
1073
+ janoffset = 0 ;
1037
1074
}
1038
1075
sp -> timecnt = timecnt ;
1039
1076
if (!timecnt )
1040
1077
sp -> typecnt = 1 ; /* Perpetual DST. */
1078
+ else if (YEARSPERREPEAT < year - yearbeg )
1079
+ sp -> goback = sp -> goahead = true;
1041
1080
}
1042
1081
else
1043
1082
{
0 commit comments