aboutsummaryrefslogtreecommitdiff
path: root/src/timezone/localtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/timezone/localtime.c')
-rw-r--r--src/timezone/localtime.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c
index 787f0b69d63..0f65f3c648e 100644
--- a/src/timezone/localtime.c
+++ b/src/timezone/localtime.c
@@ -92,6 +92,7 @@ struct rule
static struct pg_tm *gmtsub(pg_time_t const *, int32, struct pg_tm *);
static bool increment_overflow(int *, int);
static bool increment_overflow_time(pg_time_t *, int32);
+static int64 leapcorr(struct state const *, pg_time_t);
static struct pg_tm *timesub(pg_time_t const *, int32, struct state const *,
struct pg_tm *);
static bool typesequiv(struct state const *, int, int);
@@ -477,12 +478,14 @@ tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
for (i = 0; i < ts->timecnt; i++)
if (sp->timecnt == 0
- || sp->ats[sp->timecnt - 1] < ts->ats[i])
+ || (sp->ats[sp->timecnt - 1]
+ < ts->ats[i] + leapcorr(sp, ts->ats[i])))
break;
while (i < ts->timecnt
&& sp->timecnt < TZ_MAX_TIMES)
{
- sp->ats[sp->timecnt] = ts->ats[i];
+ sp->ats[sp->timecnt]
+ = ts->ats[i] + leapcorr(sp, ts->ats[i]);
sp->types[sp->timecnt] = (sp->typecnt
+ ts->types[i]);
sp->timecnt++;
@@ -1601,6 +1604,22 @@ increment_overflow_time(pg_time_t *tp, int32 j)
return false;
}
+static int64
+leapcorr(struct state const *sp, pg_time_t t)
+{
+ struct lsinfo const *lp;
+ int i;
+
+ i = sp->leapcnt;
+ while (--i >= 0)
+ {
+ lp = &sp->lsis[i];
+ if (t >= lp->ls_trans)
+ return lp->ls_corr;
+ }
+ return 0;
+}
+
/*
* Find the next DST transition time in the given zone after the given time
*