Coverage Report

Created: 2025-10-09 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/timezone/localtime.c
Line
Count
Source
1
/* Convert timestamp from pg_time_t to struct pg_tm.  */
2
3
/*
4
 * This file is in the public domain, so clarified as of
5
 * 1996-06-05 by Arthur David Olson.
6
 *
7
 * IDENTIFICATION
8
 *    src/timezone/localtime.c
9
 */
10
11
/*
12
 * Leap second handling from Bradley White.
13
 * POSIX-style TZ environment variable handling from Guy Harris.
14
 */
15
16
/* this file needs to build in both frontend and backend contexts */
17
#include "c.h"
18
19
#include <fcntl.h>
20
21
#include "datatype/timestamp.h"
22
#include "pgtz.h"
23
24
#include "private.h"
25
#include "tzfile.h"
26
27
28
#ifndef WILDABBR
29
/*
30
 * Someone might make incorrect use of a time zone abbreviation:
31
 *  1.  They might reference tzname[0] before calling tzset (explicitly
32
 *    or implicitly).
33
 *  2.  They might reference tzname[1] before calling tzset (explicitly
34
 *    or implicitly).
35
 *  3.  They might reference tzname[1] after setting to a time zone
36
 *    in which Daylight Saving Time is never observed.
37
 *  4.  They might reference tzname[0] after setting to a time zone
38
 *    in which Standard Time is never observed.
39
 *  5.  They might reference tm.tm_zone after calling offtime.
40
 * What's best to do in the above cases is open to debate;
41
 * for now, we just set things up so that in any of the five cases
42
 * WILDABBR is used. Another possibility: initialize tzname[0] to the
43
 * string "tzname[0] used before set", and similarly for the other cases.
44
 * And another: initialize tzname[0] to "ERA", with an explanation in the
45
 * manual page of what this "time zone abbreviation" means (doing this so
46
 * that tzname[0] has the "normal" length of three characters).
47
 */
48
#define WILDABBR  "   "
49
#endif              /* !defined WILDABBR */
50
51
static const char wildabbr[] = WILDABBR;
52
53
static const char gmt[] = "GMT";
54
55
/*
56
 * The DST rules to use if a POSIX TZ string has no rules.
57
 * Default to US rules as of 2017-05-07.
58
 * POSIX does not specify the default DST rules;
59
 * for historical reasons, US rules are a common default.
60
 */
61
0
#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
62
63
/* structs ttinfo, lsinfo, state have been moved to pgtz.h */
64
65
enum r_type
66
{
67
  JULIAN_DAY,         /* Jn = Julian day */
68
  DAY_OF_YEAR,        /* n = day of year */
69
  MONTH_NTH_DAY_OF_WEEK,    /* Mm.n.d = month, week, day of week */
70
};
71
72
struct rule
73
{
74
  enum r_type r_type;     /* type of rule */
75
  int     r_day;      /* day number of rule */
76
  int     r_week;     /* week number of rule */
77
  int     r_mon;      /* month number of rule */
78
  int32   r_time;     /* transition time of rule */
79
};
80
81
/*
82
 * Prototypes for static functions.
83
 */
84
85
static struct pg_tm *gmtsub(pg_time_t const *timep, int32 offset,
86
              struct pg_tm *tmp);
87
static bool increment_overflow(int *ip, int j);
88
static bool increment_overflow_time(pg_time_t *tp, int32 j);
89
static int64 leapcorr(struct state const *sp, pg_time_t t);
90
static struct pg_tm *timesub(pg_time_t const *timep,
91
               int32 offset, struct state const *sp,
92
               struct pg_tm *tmp);
93
static bool typesequiv(struct state const *sp, int a, int b);
94
95
96
/*
97
 * Section 4.12.3 of X3.159-1989 requires that
98
 *  Except for the strftime function, these functions [asctime,
99
 *  ctime, gmtime, localtime] return values in one of two static
100
 *  objects: a broken-down time structure and an array of char.
101
 * Thanks to Paul Eggert for noting this.
102
 */
103
104
static struct pg_tm tm;
105
106
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
107
static void
108
init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
109
2
{
110
2
  s->tt_utoff = utoff;
111
2
  s->tt_isdst = isdst;
112
2
  s->tt_desigidx = desigidx;
113
2
  s->tt_ttisstd = false;
114
2
  s->tt_ttisut = false;
115
2
}
116
117
static int32
118
detzcode(const char *const codep)
119
0
{
120
0
  int32   result;
121
0
  int     i;
122
0
  int32   one = 1;
123
0
  int32   halfmaxval = one << (32 - 2);
124
0
  int32   maxval = halfmaxval - 1 + halfmaxval;
125
0
  int32   minval = -1 - maxval;
126
127
0
  result = codep[0] & 0x7f;
128
0
  for (i = 1; i < 4; ++i)
129
0
    result = (result << 8) | (codep[i] & 0xff);
130
131
0
  if (codep[0] & 0x80)
132
0
  {
133
    /*
134
     * Do two's-complement negation even on non-two's-complement machines.
135
     * If the result would be minval - 1, return minval.
136
     */
137
0
    result -= !TWOS_COMPLEMENT(int32) && result != 0;
138
0
    result += minval;
139
0
  }
140
0
  return result;
141
0
}
142
143
static int64
144
detzcode64(const char *const codep)
145
0
{
146
0
  uint64    result;
147
0
  int     i;
148
0
  int64   one = 1;
149
0
  int64   halfmaxval = one << (64 - 2);
150
0
  int64   maxval = halfmaxval - 1 + halfmaxval;
151
0
  int64   minval = -TWOS_COMPLEMENT(int64) - maxval;
152
153
0
  result = codep[0] & 0x7f;
154
0
  for (i = 1; i < 8; ++i)
155
0
    result = (result << 8) | (codep[i] & 0xff);
156
157
0
  if (codep[0] & 0x80)
158
0
  {
159
    /*
160
     * Do two's-complement negation even on non-two's-complement machines.
161
     * If the result would be minval - 1, return minval.
162
     */
163
0
    result -= !TWOS_COMPLEMENT(int64) && result != 0;
164
0
    result += minval;
165
0
  }
166
0
  return result;
167
0
}
168
169
static bool
170
differ_by_repeat(const pg_time_t t1, const pg_time_t t0)
171
0
{
172
0
  if (TYPE_BIT(pg_time_t) - TYPE_SIGNED(pg_time_t) < SECSPERREPEAT_BITS)
173
0
    return 0;
174
0
  return t1 - t0 == SECSPERREPEAT;
175
0
}
176
177
/* Input buffer for data read from a compiled tz file.  */
178
union input_buffer
179
{
180
  /* The first part of the buffer, interpreted as a header.  */
181
  struct tzhead tzhead;
182
183
  /* The entire buffer.  */
184
  char    buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
185
          + 4 * TZ_MAX_TIMES];
186
};
187
188
/* Local storage needed for 'tzloadbody'.  */
189
union local_storage
190
{
191
  /* The results of analyzing the file's contents after it is opened.  */
192
  struct file_analysis
193
  {
194
    /* The input buffer.  */
195
    union input_buffer u;
196
197
    /* A temporary state used for parsing a TZ string in the file.  */
198
    struct state st;
199
  }     u;
200
201
  /* We don't need the "fullname" member */
202
};
203
204
/* Load tz data from the file named NAME into *SP.  Read extended
205
 * format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
206
 * success, an errno value on failure.
207
 * PG: If "canonname" is not NULL, then on success the canonical spelling of
208
 * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
209
 */
210
static int
211
tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
212
       union local_storage *lsp)
213
0
{
214
0
  int     i;
215
0
  int     fid;
216
0
  int     stored;
217
0
  ssize_t   nread;
218
0
  union input_buffer *up = &lsp->u.u;
219
0
  int     tzheadsize = sizeof(struct tzhead);
220
221
0
  sp->goback = sp->goahead = false;
222
223
0
  if (!name)
224
0
  {
225
0
    name = TZDEFAULT;
226
0
    if (!name)
227
0
      return EINVAL;
228
0
  }
229
230
0
  if (name[0] == ':')
231
0
    ++name;
232
233
0
  fid = pg_open_tzfile(name, canonname);
234
0
  if (fid < 0)
235
0
    return ENOENT;     /* pg_open_tzfile may not set errno */
236
237
0
  nread = read(fid, up->buf, sizeof up->buf);
238
0
  if (nread < tzheadsize)
239
0
  {
240
0
    int     err = nread < 0 ? errno : EINVAL;
241
242
0
    close(fid);
243
0
    return err;
244
0
  }
245
0
  if (close(fid) < 0)
246
0
    return errno;
247
0
  for (stored = 4; stored <= 8; stored *= 2)
248
0
  {
249
0
    int32   ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
250
0
    int32   ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
251
0
    int64   prevtr = 0;
252
0
    int32   prevcorr = 0;
253
0
    int32   leapcnt = detzcode(up->tzhead.tzh_leapcnt);
254
0
    int32   timecnt = detzcode(up->tzhead.tzh_timecnt);
255
0
    int32   typecnt = detzcode(up->tzhead.tzh_typecnt);
256
0
    int32   charcnt = detzcode(up->tzhead.tzh_charcnt);
257
0
    char const *p = up->buf + tzheadsize;
258
259
    /*
260
     * Although tzfile(5) currently requires typecnt to be nonzero,
261
     * support future formats that may allow zero typecnt in files that
262
     * have a TZ string and no transitions.
263
     */
264
0
    if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
265
0
        && 0 <= typecnt && typecnt < TZ_MAX_TYPES
266
0
        && 0 <= timecnt && timecnt < TZ_MAX_TIMES
267
0
        && 0 <= charcnt && charcnt < TZ_MAX_CHARS
268
0
        && (ttisstdcnt == typecnt || ttisstdcnt == 0)
269
0
        && (ttisutcnt == typecnt || ttisutcnt == 0)))
270
0
      return EINVAL;
271
0
    if (nread
272
0
      < (tzheadsize   /* struct tzhead */
273
0
         + timecnt * stored /* ats */
274
0
         + timecnt    /* types */
275
0
         + typecnt * 6  /* ttinfos */
276
0
         + charcnt    /* chars */
277
0
         + leapcnt * (stored + 4) /* lsinfos */
278
0
         + ttisstdcnt   /* ttisstds */
279
0
         + ttisutcnt)) /* ttisuts */
280
0
      return EINVAL;
281
0
    sp->leapcnt = leapcnt;
282
0
    sp->timecnt = timecnt;
283
0
    sp->typecnt = typecnt;
284
0
    sp->charcnt = charcnt;
285
286
    /*
287
     * 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.
290
     */
291
0
    timecnt = 0;
292
0
    for (i = 0; i < sp->timecnt; ++i)
293
0
    {
294
0
      int64   at
295
0
      = stored == 4 ? detzcode(p) : detzcode64(p);
296
297
0
      sp->types[i] = at <= TIME_T_MAX;
298
0
      if (sp->types[i])
299
0
      {
300
0
        pg_time_t attime
301
0
        = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
302
0
           ? TIME_T_MIN : at);
303
304
0
        if (timecnt && attime <= sp->ats[timecnt - 1])
305
0
        {
306
0
          if (attime < sp->ats[timecnt - 1])
307
0
            return EINVAL;
308
0
          sp->types[i - 1] = 0;
309
0
          timecnt--;
310
0
        }
311
0
        sp->ats[timecnt++] = attime;
312
0
      }
313
0
      p += stored;
314
0
    }
315
316
0
    timecnt = 0;
317
0
    for (i = 0; i < sp->timecnt; ++i)
318
0
    {
319
0
      unsigned char typ = *p++;
320
321
0
      if (sp->typecnt <= typ)
322
0
        return EINVAL;
323
0
      if (sp->types[i])
324
0
        sp->types[timecnt++] = typ;
325
0
    }
326
0
    sp->timecnt = timecnt;
327
0
    for (i = 0; i < sp->typecnt; ++i)
328
0
    {
329
0
      struct ttinfo *ttisp;
330
0
      unsigned char isdst,
331
0
            desigidx;
332
333
0
      ttisp = &sp->ttis[i];
334
0
      ttisp->tt_utoff = detzcode(p);
335
0
      p += 4;
336
0
      isdst = *p++;
337
0
      if (!(isdst < 2))
338
0
        return EINVAL;
339
0
      ttisp->tt_isdst = isdst;
340
0
      desigidx = *p++;
341
0
      if (!(desigidx < sp->charcnt))
342
0
        return EINVAL;
343
0
      ttisp->tt_desigidx = desigidx;
344
0
    }
345
0
    for (i = 0; i < sp->charcnt; ++i)
346
0
      sp->chars[i] = *p++;
347
0
    sp->chars[i] = '\0';  /* ensure '\0' at end */
348
349
    /* Read leap seconds, discarding those out of pg_time_t range.  */
350
0
    leapcnt = 0;
351
0
    for (i = 0; i < sp->leapcnt; ++i)
352
0
    {
353
0
      int64   tr = stored == 4 ? detzcode(p) : detzcode64(p);
354
0
      int32   corr = detzcode(p + stored);
355
356
0
      p += stored + 4;
357
      /* Leap seconds cannot occur before the Epoch.  */
358
0
      if (tr < 0)
359
0
        return EINVAL;
360
0
      if (tr <= TIME_T_MAX)
361
0
      {
362
        /*
363
         * Leap seconds cannot occur more than once per UTC month, and
364
         * UTC months are at least 28 days long (minus 1 second for a
365
         * negative leap second).  Each leap second's correction must
366
         * differ from the previous one's by 1 second.
367
         */
368
0
        if (tr - prevtr < 28 * SECSPERDAY - 1
369
0
          || (corr != prevcorr - 1 && corr != prevcorr + 1))
370
0
          return EINVAL;
371
0
        sp->lsis[leapcnt].ls_trans = prevtr = tr;
372
0
        sp->lsis[leapcnt].ls_corr = prevcorr = corr;
373
0
        leapcnt++;
374
0
      }
375
0
    }
376
0
    sp->leapcnt = leapcnt;
377
378
0
    for (i = 0; i < sp->typecnt; ++i)
379
0
    {
380
0
      struct ttinfo *ttisp;
381
382
0
      ttisp = &sp->ttis[i];
383
0
      if (ttisstdcnt == 0)
384
0
        ttisp->tt_ttisstd = false;
385
0
      else
386
0
      {
387
0
        if (*p != true && *p != false)
388
0
          return EINVAL;
389
0
        ttisp->tt_ttisstd = *p++;
390
0
      }
391
0
    }
392
0
    for (i = 0; i < sp->typecnt; ++i)
393
0
    {
394
0
      struct ttinfo *ttisp;
395
396
0
      ttisp = &sp->ttis[i];
397
0
      if (ttisutcnt == 0)
398
0
        ttisp->tt_ttisut = false;
399
0
      else
400
0
      {
401
0
        if (*p != true && *p != false)
402
0
          return EINVAL;
403
0
        ttisp->tt_ttisut = *p++;
404
0
      }
405
0
    }
406
407
    /*
408
     * If this is an old file, we're done.
409
     */
410
0
    if (up->tzhead.tzh_version[0] == '\0')
411
0
      break;
412
0
    nread -= p - up->buf;
413
0
    memmove(up->buf, p, nread);
414
0
  }
415
0
  if (doextend && nread > 2 &&
416
0
    up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
417
0
    sp->typecnt + 2 <= TZ_MAX_TYPES)
418
0
  {
419
0
    struct state *ts = &lsp->u.st;
420
421
0
    up->buf[nread - 1] = '\0';
422
0
    if (tzparse(&up->buf[1], ts, false))
423
0
    {
424
      /*
425
       * Attempt to reuse existing abbreviations. Without this,
426
       * America/Anchorage would be right on the edge after 2037 when
427
       * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
428
       * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
429
       * AKST AKDT).  Reusing means sp->charcnt can stay 40 in this
430
       * example.
431
       */
432
0
      int     gotabbr = 0;
433
0
      int     charcnt = sp->charcnt;
434
435
0
      for (i = 0; i < ts->typecnt; i++)
436
0
      {
437
0
        char     *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
438
0
        int     j;
439
440
0
        for (j = 0; j < charcnt; j++)
441
0
          if (strcmp(sp->chars + j, tsabbr) == 0)
442
0
          {
443
0
            ts->ttis[i].tt_desigidx = j;
444
0
            gotabbr++;
445
0
            break;
446
0
          }
447
0
        if (!(j < charcnt))
448
0
        {
449
0
          int     tsabbrlen = strlen(tsabbr);
450
451
0
          if (j + tsabbrlen < TZ_MAX_CHARS)
452
0
          {
453
0
            strcpy(sp->chars + j, tsabbr);
454
0
            charcnt = j + tsabbrlen + 1;
455
0
            ts->ttis[i].tt_desigidx = j;
456
0
            gotabbr++;
457
0
          }
458
0
        }
459
0
      }
460
0
      if (gotabbr == ts->typecnt)
461
0
      {
462
0
        sp->charcnt = charcnt;
463
464
        /*
465
         * Ignore any trailing, no-op transitions generated by zic as
466
         * they don't help here and can run afoul of bugs in zic 2016j
467
         * or earlier.
468
         */
469
0
        while (1 < sp->timecnt
470
0
             && (sp->types[sp->timecnt - 1]
471
0
               == sp->types[sp->timecnt - 2]))
472
0
          sp->timecnt--;
473
474
0
        for (i = 0; i < ts->timecnt; i++)
475
0
          if (sp->timecnt == 0
476
0
            || (sp->ats[sp->timecnt - 1]
477
0
              < ts->ats[i] + leapcorr(sp, ts->ats[i])))
478
0
            break;
479
0
        while (i < ts->timecnt
480
0
             && sp->timecnt < TZ_MAX_TIMES)
481
0
        {
482
0
          sp->ats[sp->timecnt]
483
0
            = ts->ats[i] + leapcorr(sp, ts->ats[i]);
484
0
          sp->types[sp->timecnt] = (sp->typecnt
485
0
                        + ts->types[i]);
486
0
          sp->timecnt++;
487
0
          i++;
488
0
        }
489
0
        for (i = 0; i < ts->typecnt; i++)
490
0
          sp->ttis[sp->typecnt++] = ts->ttis[i];
491
0
      }
492
0
    }
493
0
  }
494
0
  if (sp->typecnt == 0)
495
0
    return EINVAL;
496
0
  if (sp->timecnt > 1)
497
0
  {
498
0
    for (i = 1; i < sp->timecnt; ++i)
499
0
      if (typesequiv(sp, sp->types[i], sp->types[0]) &&
500
0
        differ_by_repeat(sp->ats[i], sp->ats[0]))
501
0
      {
502
0
        sp->goback = true;
503
0
        break;
504
0
      }
505
0
    for (i = sp->timecnt - 2; i >= 0; --i)
506
0
      if (typesequiv(sp, sp->types[sp->timecnt - 1],
507
0
               sp->types[i]) &&
508
0
        differ_by_repeat(sp->ats[sp->timecnt - 1],
509
0
                 sp->ats[i]))
510
0
      {
511
0
        sp->goahead = true;
512
0
        break;
513
0
      }
514
0
  }
515
516
  /*
517
   * Infer sp->defaulttype from the data.  Although this default type is
518
   * always zero for data from recent tzdb releases, things are trickier for
519
   * data from tzdb 2018e or earlier.
520
   *
521
   * The first set of heuristics work around bugs in 32-bit data generated
522
   * by tzdb 2013c or earlier.  The workaround is for zones like
523
   * Australia/Macquarie where timestamps before the first transition have a
524
   * time type that is not the earliest standard-time type.  See:
525
   * https://mm.icann.org/pipermail/tz/2013-May/019368.html
526
   */
527
528
  /*
529
   * If type 0 is unused in transitions, it's the type to use for early
530
   * times.
531
   */
532
0
  for (i = 0; i < sp->timecnt; ++i)
533
0
    if (sp->types[i] == 0)
534
0
      break;
535
0
  i = i < sp->timecnt ? -1 : 0;
536
537
  /*
538
   * Absent the above, if there are transition times and the first
539
   * transition is to a daylight time find the standard type less than and
540
   * closest to the type of the first transition.
541
   */
542
0
  if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst)
543
0
  {
544
0
    i = sp->types[0];
545
0
    while (--i >= 0)
546
0
      if (!sp->ttis[i].tt_isdst)
547
0
        break;
548
0
  }
549
550
  /*
551
   * The next heuristics are for data generated by tzdb 2018e or earlier,
552
   * for zones like EST5EDT where the first transition is to DST.
553
   */
554
555
  /*
556
   * If no result yet, find the first standard type. If there is none, punt
557
   * to type zero.
558
   */
559
0
  if (i < 0)
560
0
  {
561
0
    i = 0;
562
0
    while (sp->ttis[i].tt_isdst)
563
0
      if (++i >= sp->typecnt)
564
0
      {
565
0
        i = 0;
566
0
        break;
567
0
      }
568
0
  }
569
570
  /*
571
   * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
572
   * worry about 2018e-or-earlier data.  Even simpler would be to remove the
573
   * defaulttype member and just use 0 in its place.
574
   */
575
0
  sp->defaulttype = i;
576
577
0
  return 0;
578
0
}
579
580
/* Load tz data from the file named NAME into *SP.  Read extended
581
 * format if DOEXTEND.  Return 0 on success, an errno value on failure.
582
 * PG: If "canonname" is not NULL, then on success the canonical spelling of
583
 * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
584
 */
585
int
586
tzload(const char *name, char *canonname, struct state *sp, bool doextend)
587
0
{
588
0
  union local_storage *lsp = malloc(sizeof *lsp);
589
590
0
  if (!lsp)
591
0
    return errno;
592
0
  else
593
0
  {
594
0
    int     err = tzloadbody(name, canonname, sp, doextend, lsp);
595
596
0
    free(lsp);
597
0
    return err;
598
0
  }
599
0
}
600
601
static bool
602
typesequiv(const struct state *sp, int a, int b)
603
0
{
604
0
  bool    result;
605
606
0
  if (sp == NULL ||
607
0
    a < 0 || a >= sp->typecnt ||
608
0
    b < 0 || b >= sp->typecnt)
609
0
    result = false;
610
0
  else
611
0
  {
612
0
    const struct ttinfo *ap = &sp->ttis[a];
613
0
    const struct ttinfo *bp = &sp->ttis[b];
614
615
0
    result = (ap->tt_utoff == bp->tt_utoff
616
0
          && ap->tt_isdst == bp->tt_isdst
617
0
          && ap->tt_ttisstd == bp->tt_ttisstd
618
0
          && ap->tt_ttisut == bp->tt_ttisut
619
0
          && (strcmp(&sp->chars[ap->tt_desigidx],
620
0
               &sp->chars[bp->tt_desigidx])
621
0
            == 0));
622
0
  }
623
0
  return result;
624
0
}
625
626
static const int mon_lengths[2][MONSPERYEAR] = {
627
  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
628
  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
629
};
630
631
static const int year_lengths[2] = {
632
  DAYSPERNYEAR, DAYSPERLYEAR
633
};
634
635
/*
636
 * Given a pointer into a timezone string, scan until a character that is not
637
 * a valid character in a time zone abbreviation is found.
638
 * Return a pointer to that character.
639
 */
640
641
static const char *
642
getzname(const char *strp)
643
0
{
644
0
  char    c;
645
646
0
  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
647
0
       c != '+')
648
0
    ++strp;
649
0
  return strp;
650
0
}
651
652
/*
653
 * Given a pointer into an extended timezone string, scan until the ending
654
 * delimiter of the time zone abbreviation is located.
655
 * Return a pointer to the delimiter.
656
 *
657
 * As with getzname above, the legal character set is actually quite
658
 * restricted, with other characters producing undefined results.
659
 * We don't do any checking here; checking is done later in common-case code.
660
 */
661
662
static const char *
663
getqzname(const char *strp, const int delim)
664
0
{
665
0
  int     c;
666
667
0
  while ((c = *strp) != '\0' && c != delim)
668
0
    ++strp;
669
0
  return strp;
670
0
}
671
672
/*
673
 * Given a pointer into a timezone string, extract a number from that string.
674
 * Check that the number is within a specified range; if it is not, return
675
 * NULL.
676
 * Otherwise, return a pointer to the first character not part of the number.
677
 */
678
679
static const char *
680
getnum(const char *strp, int *const nump, const int min, const int max)
681
0
{
682
0
  char    c;
683
0
  int     num;
684
685
0
  if (strp == NULL || !is_digit(c = *strp))
686
0
    return NULL;
687
0
  num = 0;
688
0
  do
689
0
  {
690
0
    num = num * 10 + (c - '0');
691
0
    if (num > max)
692
0
      return NULL;   /* illegal value */
693
0
    c = *++strp;
694
0
  } while (is_digit(c));
695
0
  if (num < min)
696
0
    return NULL;     /* illegal value */
697
0
  *nump = num;
698
0
  return strp;
699
0
}
700
701
/*
702
 * Given a pointer into a timezone string, extract a number of seconds,
703
 * in hh[:mm[:ss]] form, from the string.
704
 * If any error occurs, return NULL.
705
 * Otherwise, return a pointer to the first character not part of the number
706
 * of seconds.
707
 */
708
709
static const char *
710
getsecs(const char *strp, int32 *const secsp)
711
0
{
712
0
  int     num;
713
714
  /*
715
   * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
716
   * "M10.4.6/26", which does not conform to Posix, but which specifies the
717
   * equivalent of "02:00 on the first Sunday on or after 23 Oct".
718
   */
719
0
  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
720
0
  if (strp == NULL)
721
0
    return NULL;
722
0
  *secsp = num * (int32) SECSPERHOUR;
723
0
  if (*strp == ':')
724
0
  {
725
0
    ++strp;
726
0
    strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
727
0
    if (strp == NULL)
728
0
      return NULL;
729
0
    *secsp += num * SECSPERMIN;
730
0
    if (*strp == ':')
731
0
    {
732
0
      ++strp;
733
      /* 'SECSPERMIN' allows for leap seconds.  */
734
0
      strp = getnum(strp, &num, 0, SECSPERMIN);
735
0
      if (strp == NULL)
736
0
        return NULL;
737
0
      *secsp += num;
738
0
    }
739
0
  }
740
0
  return strp;
741
0
}
742
743
/*
744
 * Given a pointer into a timezone string, extract an offset, in
745
 * [+-]hh[:mm[:ss]] form, from the string.
746
 * If any error occurs, return NULL.
747
 * Otherwise, return a pointer to the first character not part of the time.
748
 */
749
750
static const char *
751
getoffset(const char *strp, int32 *const offsetp)
752
0
{
753
0
  bool    neg = false;
754
755
0
  if (*strp == '-')
756
0
  {
757
0
    neg = true;
758
0
    ++strp;
759
0
  }
760
0
  else if (*strp == '+')
761
0
    ++strp;
762
0
  strp = getsecs(strp, offsetp);
763
0
  if (strp == NULL)
764
0
    return NULL;     /* illegal time */
765
0
  if (neg)
766
0
    *offsetp = -*offsetp;
767
0
  return strp;
768
0
}
769
770
/*
771
 * Given a pointer into a timezone string, extract a rule in the form
772
 * date[/time]. See POSIX section 8 for the format of "date" and "time".
773
 * If a valid rule is not found, return NULL.
774
 * Otherwise, return a pointer to the first character not part of the rule.
775
 */
776
777
static const char *
778
getrule(const char *strp, struct rule *const rulep)
779
0
{
780
0
  if (*strp == 'J')
781
0
  {
782
    /*
783
     * Julian day.
784
     */
785
0
    rulep->r_type = JULIAN_DAY;
786
0
    ++strp;
787
0
    strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
788
0
  }
789
0
  else if (*strp == 'M')
790
0
  {
791
    /*
792
     * Month, week, day.
793
     */
794
0
    rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
795
0
    ++strp;
796
0
    strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
797
0
    if (strp == NULL)
798
0
      return NULL;
799
0
    if (*strp++ != '.')
800
0
      return NULL;
801
0
    strp = getnum(strp, &rulep->r_week, 1, 5);
802
0
    if (strp == NULL)
803
0
      return NULL;
804
0
    if (*strp++ != '.')
805
0
      return NULL;
806
0
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
807
0
  }
808
0
  else if (is_digit(*strp))
809
0
  {
810
    /*
811
     * Day of year.
812
     */
813
0
    rulep->r_type = DAY_OF_YEAR;
814
0
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
815
0
  }
816
0
  else
817
0
    return NULL;     /* invalid format */
818
0
  if (strp == NULL)
819
0
    return NULL;
820
0
  if (*strp == '/')
821
0
  {
822
    /*
823
     * Time specified.
824
     */
825
0
    ++strp;
826
0
    strp = getoffset(strp, &rulep->r_time);
827
0
  }
828
0
  else
829
0
    rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
830
0
  return strp;
831
0
}
832
833
/*
834
 * Given a year, a rule, and the offset from UT at the time that rule takes
835
 * effect, calculate the year-relative time that rule takes effect.
836
 */
837
838
static int32
839
transtime(const int year, const struct rule *const rulep,
840
      const int32 offset)
841
0
{
842
0
  bool    leapyear;
843
0
  int32   value;
844
0
  int     i;
845
0
  int     d,
846
0
        m1,
847
0
        yy0,
848
0
        yy1,
849
0
        yy2,
850
0
        dow;
851
852
0
  INITIALIZE(value);
853
0
  leapyear = isleap(year);
854
0
  switch (rulep->r_type)
855
0
  {
856
857
0
    case JULIAN_DAY:
858
859
      /*
860
       * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
861
       * years. In non-leap years, or if the day number is 59 or less,
862
       * just add SECSPERDAY times the day number-1 to the time of
863
       * January 1, midnight, to get the day.
864
       */
865
0
      value = (rulep->r_day - 1) * SECSPERDAY;
866
0
      if (leapyear && rulep->r_day >= 60)
867
0
        value += SECSPERDAY;
868
0
      break;
869
870
0
    case DAY_OF_YEAR:
871
872
      /*
873
       * n - day of year. Just add SECSPERDAY times the day number to
874
       * the time of January 1, midnight, to get the day.
875
       */
876
0
      value = rulep->r_day * SECSPERDAY;
877
0
      break;
878
879
0
    case MONTH_NTH_DAY_OF_WEEK:
880
881
      /*
882
       * Mm.n.d - nth "dth day" of month m.
883
       */
884
885
      /*
886
       * Use Zeller's Congruence to get day-of-week of first day of
887
       * month.
888
       */
889
0
      m1 = (rulep->r_mon + 9) % 12 + 1;
890
0
      yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
891
0
      yy1 = yy0 / 100;
892
0
      yy2 = yy0 % 100;
893
0
      dow = ((26 * m1 - 2) / 10 +
894
0
           1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
895
0
      if (dow < 0)
896
0
        dow += DAYSPERWEEK;
897
898
      /*
899
       * "dow" is the day-of-week of the first day of the month. Get the
900
       * day-of-month (zero-origin) of the first "dow" day of the month.
901
       */
902
0
      d = rulep->r_day - dow;
903
0
      if (d < 0)
904
0
        d += DAYSPERWEEK;
905
0
      for (i = 1; i < rulep->r_week; ++i)
906
0
      {
907
0
        if (d + DAYSPERWEEK >=
908
0
          mon_lengths[(int) leapyear][rulep->r_mon - 1])
909
0
          break;
910
0
        d += DAYSPERWEEK;
911
0
      }
912
913
      /*
914
       * "d" is the day-of-month (zero-origin) of the day we want.
915
       */
916
0
      value = d * SECSPERDAY;
917
0
      for (i = 0; i < rulep->r_mon - 1; ++i)
918
0
        value += mon_lengths[(int) leapyear][i] * SECSPERDAY;
919
0
      break;
920
0
  }
921
922
  /*
923
   * "value" is the year-relative time of 00:00:00 UT on the day in
924
   * question. To get the year-relative time of the specified local time on
925
   * that day, add the transition time and the current offset from UT.
926
   */
927
0
  return value + rulep->r_time + offset;
928
0
}
929
930
/*
931
 * Given a POSIX section 8-style TZ string, fill in the rule tables as
932
 * appropriate.
933
 * Returns true on success, false on failure.
934
 */
935
bool
936
tzparse(const char *name, struct state *sp, bool lastditch)
937
2
{
938
2
  const char *stdname;
939
2
  const char *dstname = NULL;
940
2
  size_t    stdlen;
941
2
  size_t    dstlen;
942
2
  size_t    charcnt;
943
2
  int32   stdoffset;
944
2
  int32   dstoffset;
945
2
  char     *cp;
946
2
  bool    load_ok;
947
948
2
  stdname = name;
949
2
  if (lastditch)
950
2
  {
951
    /* Unlike IANA, don't assume name is exactly "GMT" */
952
2
    stdlen = strlen(name);  /* length of standard zone name */
953
2
    name += stdlen;
954
2
    stdoffset = 0;
955
2
  }
956
0
  else
957
0
  {
958
0
    if (*name == '<')
959
0
    {
960
0
      name++;
961
0
      stdname = name;
962
0
      name = getqzname(name, '>');
963
0
      if (*name != '>')
964
0
        return false;
965
0
      stdlen = name - stdname;
966
0
      name++;
967
0
    }
968
0
    else
969
0
    {
970
0
      name = getzname(name);
971
0
      stdlen = name - stdname;
972
0
    }
973
0
    if (*name == '\0')   /* we allow empty STD abbrev, unlike IANA */
974
0
      return false;
975
0
    name = getoffset(name, &stdoffset);
976
0
    if (name == NULL)
977
0
      return false;
978
0
  }
979
2
  charcnt = stdlen + 1;
980
2
  if (sizeof sp->chars < charcnt)
981
0
    return false;
982
983
  /*
984
   * The IANA code always tries to tzload(TZDEFRULES) here.  We do not want
985
   * to do that; it would be bad news in the lastditch case, where we can't
986
   * assume pg_open_tzfile() is sane yet.  Moreover, if we did load it and
987
   * it contains leap-second-dependent info, that would cause problems too.
988
   * Finally, IANA has deprecated the TZDEFRULES feature, so it presumably
989
   * will die at some point.  Desupporting it now seems like good
990
   * future-proofing.
991
   */
992
2
  load_ok = false;
993
2
  sp->goback = sp->goahead = false;  /* simulate failed tzload() */
994
2
  sp->leapcnt = 0;      /* intentionally assume no leap seconds */
995
996
2
  if (*name != '\0')
997
0
  {
998
0
    if (*name == '<')
999
0
    {
1000
0
      dstname = ++name;
1001
0
      name = getqzname(name, '>');
1002
0
      if (*name != '>')
1003
0
        return false;
1004
0
      dstlen = name - dstname;
1005
0
      name++;
1006
0
    }
1007
0
    else
1008
0
    {
1009
0
      dstname = name;
1010
0
      name = getzname(name);
1011
0
      dstlen = name - dstname;  /* length of DST abbr. */
1012
0
    }
1013
0
    if (!dstlen)
1014
0
      return false;
1015
0
    charcnt += dstlen + 1;
1016
0
    if (sizeof sp->chars < charcnt)
1017
0
      return false;
1018
0
    if (*name != '\0' && *name != ',' && *name != ';')
1019
0
    {
1020
0
      name = getoffset(name, &dstoffset);
1021
0
      if (name == NULL)
1022
0
        return false;
1023
0
    }
1024
0
    else
1025
0
      dstoffset = stdoffset - SECSPERHOUR;
1026
0
    if (*name == '\0' && !load_ok)
1027
0
      name = TZDEFRULESTRING;
1028
0
    if (*name == ',' || *name == ';')
1029
0
    {
1030
0
      struct rule start;
1031
0
      struct rule end;
1032
0
      int     year;
1033
0
      int     yearlim;
1034
0
      int     timecnt;
1035
0
      pg_time_t janfirst;
1036
0
      int32   janoffset = 0;
1037
0
      int     yearbeg;
1038
1039
0
      ++name;
1040
0
      if ((name = getrule(name, &start)) == NULL)
1041
0
        return false;
1042
0
      if (*name++ != ',')
1043
0
        return false;
1044
0
      if ((name = getrule(name, &end)) == NULL)
1045
0
        return false;
1046
0
      if (*name != '\0')
1047
0
        return false;
1048
0
      sp->typecnt = 2;  /* standard time and DST */
1049
1050
      /*
1051
       * Two transitions per year, from EPOCH_YEAR forward.
1052
       */
1053
0
      init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1054
0
      init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1055
0
      sp->defaulttype = 0;
1056
0
      timecnt = 0;
1057
0
      janfirst = 0;
1058
0
      yearbeg = EPOCH_YEAR;
1059
1060
0
      do
1061
0
      {
1062
0
        int32   yearsecs
1063
0
        = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1064
1065
0
        yearbeg--;
1066
0
        if (increment_overflow_time(&janfirst, -yearsecs))
1067
0
        {
1068
0
          janoffset = -yearsecs;
1069
0
          break;
1070
0
        }
1071
0
      } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1072
1073
0
      yearlim = yearbeg + YEARSPERREPEAT + 1;
1074
0
      for (year = yearbeg; year < yearlim; year++)
1075
0
      {
1076
0
        int32
1077
0
              starttime = transtime(year, &start, stdoffset),
1078
0
              endtime = transtime(year, &end, dstoffset);
1079
0
        int32
1080
0
              yearsecs = (year_lengths[isleap(year)]
1081
0
                    * SECSPERDAY);
1082
0
        bool    reversed = endtime < starttime;
1083
1084
0
        if (reversed)
1085
0
        {
1086
0
          int32   swap = starttime;
1087
1088
0
          starttime = endtime;
1089
0
          endtime = swap;
1090
0
        }
1091
0
        if (reversed
1092
0
          || (starttime < endtime
1093
0
            && (endtime - starttime
1094
0
              < (yearsecs
1095
0
                 + (stdoffset - dstoffset)))))
1096
0
        {
1097
0
          if (TZ_MAX_TIMES - 2 < timecnt)
1098
0
            break;
1099
0
          sp->ats[timecnt] = janfirst;
1100
0
          if (!increment_overflow_time
1101
0
            (&sp->ats[timecnt],
1102
0
             janoffset + starttime))
1103
0
            sp->types[timecnt++] = !reversed;
1104
0
          sp->ats[timecnt] = janfirst;
1105
0
          if (!increment_overflow_time
1106
0
            (&sp->ats[timecnt],
1107
0
             janoffset + endtime))
1108
0
          {
1109
0
            sp->types[timecnt++] = reversed;
1110
0
            yearlim = year + YEARSPERREPEAT + 1;
1111
0
          }
1112
0
        }
1113
0
        if (increment_overflow_time
1114
0
          (&janfirst, janoffset + yearsecs))
1115
0
          break;
1116
0
        janoffset = 0;
1117
0
      }
1118
0
      sp->timecnt = timecnt;
1119
0
      if (!timecnt)
1120
0
      {
1121
0
        sp->ttis[0] = sp->ttis[1];
1122
0
        sp->typecnt = 1;  /* Perpetual DST.  */
1123
0
      }
1124
0
      else if (YEARSPERREPEAT < year - yearbeg)
1125
0
        sp->goback = sp->goahead = true;
1126
0
    }
1127
0
    else
1128
0
    {
1129
0
      int32   theirstdoffset;
1130
0
      int32   theirdstoffset;
1131
0
      int32   theiroffset;
1132
0
      bool    isdst;
1133
0
      int     i;
1134
0
      int     j;
1135
1136
0
      if (*name != '\0')
1137
0
        return false;
1138
1139
      /*
1140
       * Initial values of theirstdoffset and theirdstoffset.
1141
       */
1142
0
      theirstdoffset = 0;
1143
0
      for (i = 0; i < sp->timecnt; ++i)
1144
0
      {
1145
0
        j = sp->types[i];
1146
0
        if (!sp->ttis[j].tt_isdst)
1147
0
        {
1148
0
          theirstdoffset =
1149
0
            -sp->ttis[j].tt_utoff;
1150
0
          break;
1151
0
        }
1152
0
      }
1153
0
      theirdstoffset = 0;
1154
0
      for (i = 0; i < sp->timecnt; ++i)
1155
0
      {
1156
0
        j = sp->types[i];
1157
0
        if (sp->ttis[j].tt_isdst)
1158
0
        {
1159
0
          theirdstoffset =
1160
0
            -sp->ttis[j].tt_utoff;
1161
0
          break;
1162
0
        }
1163
0
      }
1164
1165
      /*
1166
       * Initially we're assumed to be in standard time.
1167
       */
1168
0
      isdst = false;
1169
0
      theiroffset = theirstdoffset;
1170
1171
      /*
1172
       * Now juggle transition times and types tracking offsets as you
1173
       * do.
1174
       */
1175
0
      for (i = 0; i < sp->timecnt; ++i)
1176
0
      {
1177
0
        j = sp->types[i];
1178
0
        sp->types[i] = sp->ttis[j].tt_isdst;
1179
0
        if (sp->ttis[j].tt_ttisut)
1180
0
        {
1181
          /* No adjustment to transition time */
1182
0
        }
1183
0
        else
1184
0
        {
1185
          /*
1186
           * If daylight saving time is in effect, and the
1187
           * transition time was not specified as standard time, add
1188
           * the daylight saving time offset to the transition time;
1189
           * otherwise, add the standard time offset to the
1190
           * transition time.
1191
           */
1192
          /*
1193
           * Transitions from DST to DDST will effectively disappear
1194
           * since POSIX provides for only one DST offset.
1195
           */
1196
0
          if (isdst && !sp->ttis[j].tt_ttisstd)
1197
0
          {
1198
0
            sp->ats[i] += dstoffset -
1199
0
              theirdstoffset;
1200
0
          }
1201
0
          else
1202
0
          {
1203
0
            sp->ats[i] += stdoffset -
1204
0
              theirstdoffset;
1205
0
          }
1206
0
        }
1207
0
        theiroffset = -sp->ttis[j].tt_utoff;
1208
0
        if (sp->ttis[j].tt_isdst)
1209
0
          theirdstoffset = theiroffset;
1210
0
        else
1211
0
          theirstdoffset = theiroffset;
1212
0
      }
1213
1214
      /*
1215
       * Finally, fill in ttis.
1216
       */
1217
0
      init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1218
0
      init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1219
0
      sp->typecnt = 2;
1220
0
      sp->defaulttype = 0;
1221
0
    }
1222
0
  }
1223
2
  else
1224
2
  {
1225
2
    dstlen = 0;
1226
2
    sp->typecnt = 1;    /* only standard time */
1227
2
    sp->timecnt = 0;
1228
2
    init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1229
2
    sp->defaulttype = 0;
1230
2
  }
1231
2
  sp->charcnt = charcnt;
1232
2
  cp = sp->chars;
1233
2
  memcpy(cp, stdname, stdlen);
1234
2
  cp += stdlen;
1235
2
  *cp++ = '\0';
1236
2
  if (dstlen != 0)
1237
0
  {
1238
0
    memcpy(cp, dstname, dstlen);
1239
0
    *(cp + dstlen) = '\0';
1240
0
  }
1241
2
  return true;
1242
2
}
1243
1244
static void
1245
gmtload(struct state *const sp)
1246
0
{
1247
0
  if (tzload(gmt, NULL, sp, true) != 0)
1248
0
    tzparse(gmt, sp, true);
1249
0
}
1250
1251
1252
/*
1253
 * The easy way to behave "as if no library function calls" localtime
1254
 * is to not call it, so we drop its guts into "localsub", which can be
1255
 * freely called. (And no, the PANS doesn't require the above behavior,
1256
 * but it *is* desirable.)
1257
 */
1258
static struct pg_tm *
1259
localsub(struct state const *sp, pg_time_t const *timep,
1260
     struct pg_tm *const tmp)
1261
4.85k
{
1262
4.85k
  const struct ttinfo *ttisp;
1263
4.85k
  int     i;
1264
4.85k
  struct pg_tm *result;
1265
4.85k
  const pg_time_t t = *timep;
1266
1267
4.85k
  if (sp == NULL)
1268
0
    return gmtsub(timep, 0, tmp);
1269
4.85k
  if ((sp->goback && t < sp->ats[0]) ||
1270
4.85k
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1271
0
  {
1272
0
    pg_time_t newt = t;
1273
0
    pg_time_t seconds;
1274
0
    pg_time_t years;
1275
1276
0
    if (t < sp->ats[0])
1277
0
      seconds = sp->ats[0] - t;
1278
0
    else
1279
0
      seconds = t - sp->ats[sp->timecnt - 1];
1280
0
    --seconds;
1281
0
    years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
1282
0
    seconds = years * AVGSECSPERYEAR;
1283
0
    if (t < sp->ats[0])
1284
0
      newt += seconds;
1285
0
    else
1286
0
      newt -= seconds;
1287
0
    if (newt < sp->ats[0] ||
1288
0
      newt > sp->ats[sp->timecnt - 1])
1289
0
      return NULL;   /* "cannot happen" */
1290
0
    result = localsub(sp, &newt, tmp);
1291
0
    if (result)
1292
0
    {
1293
0
      int64   newy;
1294
1295
0
      newy = result->tm_year;
1296
0
      if (t < sp->ats[0])
1297
0
        newy -= years;
1298
0
      else
1299
0
        newy += years;
1300
0
      if (!(INT_MIN <= newy && newy <= INT_MAX))
1301
0
        return NULL;
1302
0
      result->tm_year = newy;
1303
0
    }
1304
0
    return result;
1305
0
  }
1306
4.85k
  if (sp->timecnt == 0 || t < sp->ats[0])
1307
4.85k
  {
1308
4.85k
    i = sp->defaulttype;
1309
4.85k
  }
1310
0
  else
1311
0
  {
1312
0
    int     lo = 1;
1313
0
    int     hi = sp->timecnt;
1314
1315
0
    while (lo < hi)
1316
0
    {
1317
0
      int     mid = (lo + hi) >> 1;
1318
1319
0
      if (t < sp->ats[mid])
1320
0
        hi = mid;
1321
0
      else
1322
0
        lo = mid + 1;
1323
0
    }
1324
0
    i = (int) sp->types[lo - 1];
1325
0
  }
1326
4.85k
  ttisp = &sp->ttis[i];
1327
1328
  /*
1329
   * To get (wrong) behavior that's compatible with System V Release 2.0
1330
   * you'd replace the statement below with t += ttisp->tt_utoff;
1331
   * timesub(&t, 0L, sp, tmp);
1332
   */
1333
4.85k
  result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1334
4.85k
  if (result)
1335
4.85k
  {
1336
4.85k
    result->tm_isdst = ttisp->tt_isdst;
1337
4.85k
    result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_desigidx]);
1338
4.85k
  }
1339
4.85k
  return result;
1340
4.85k
}
1341
1342
1343
struct pg_tm *
1344
pg_localtime(const pg_time_t *timep, const pg_tz *tz)
1345
4.85k
{
1346
4.85k
  return localsub(&tz->state, timep, &tm);
1347
4.85k
}
1348
1349
1350
/*
1351
 * gmtsub is to gmtime as localsub is to localtime.
1352
 *
1353
 * Except we have a private "struct state" for GMT, so no sp is passed in.
1354
 */
1355
1356
static struct pg_tm *
1357
gmtsub(pg_time_t const *timep, int32 offset,
1358
     struct pg_tm *tmp)
1359
0
{
1360
0
  struct pg_tm *result;
1361
1362
  /* GMT timezone state data is kept here */
1363
0
  static struct state *gmtptr = NULL;
1364
1365
0
  if (gmtptr == NULL)
1366
0
  {
1367
    /* Allocate on first use */
1368
0
    gmtptr = (struct state *) malloc(sizeof(struct state));
1369
0
    if (gmtptr == NULL)
1370
0
      return NULL;   /* errno should be set by malloc */
1371
0
    gmtload(gmtptr);
1372
0
  }
1373
1374
0
  result = timesub(timep, offset, gmtptr, tmp);
1375
1376
  /*
1377
   * Could get fancy here and deliver something such as "+xx" or "-xx" if
1378
   * offset is non-zero, but this is no time for a treasure hunt.
1379
   */
1380
0
  if (offset != 0)
1381
0
    tmp->tm_zone = wildabbr;
1382
0
  else
1383
0
    tmp->tm_zone = gmtptr->chars;
1384
1385
0
  return result;
1386
0
}
1387
1388
struct pg_tm *
1389
pg_gmtime(const pg_time_t *timep)
1390
0
{
1391
0
  return gmtsub(timep, 0, &tm);
1392
0
}
1393
1394
/*
1395
 * Return the number of leap years through the end of the given year
1396
 * where, to make the math easy, the answer for year zero is defined as zero.
1397
 */
1398
1399
static int
1400
leaps_thru_end_of_nonneg(int y)
1401
19.4k
{
1402
19.4k
  return y / 4 - y / 100 + y / 400;
1403
19.4k
}
1404
1405
static int
1406
leaps_thru_end_of(const int y)
1407
19.4k
{
1408
19.4k
  return (y < 0
1409
19.4k
      ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1410
19.4k
      : leaps_thru_end_of_nonneg(y));
1411
19.4k
}
1412
1413
static struct pg_tm *
1414
timesub(const pg_time_t *timep, int32 offset,
1415
    const struct state *sp, struct pg_tm *tmp)
1416
4.85k
{
1417
4.85k
  const struct lsinfo *lp;
1418
4.85k
  pg_time_t tdays;
1419
4.85k
  int     idays;      /* unsigned would be so 2003 */
1420
4.85k
  int64   rem;
1421
4.85k
  int     y;
1422
4.85k
  const int  *ip;
1423
4.85k
  int64   corr;
1424
4.85k
  bool    hit;
1425
4.85k
  int     i;
1426
1427
4.85k
  corr = 0;
1428
4.85k
  hit = false;
1429
4.85k
  i = (sp == NULL) ? 0 : sp->leapcnt;
1430
4.85k
  while (--i >= 0)
1431
0
  {
1432
0
    lp = &sp->lsis[i];
1433
0
    if (*timep >= lp->ls_trans)
1434
0
    {
1435
0
      corr = lp->ls_corr;
1436
0
      hit = (*timep == lp->ls_trans
1437
0
           && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
1438
0
      break;
1439
0
    }
1440
0
  }
1441
4.85k
  y = EPOCH_YEAR;
1442
4.85k
  tdays = *timep / SECSPERDAY;
1443
4.85k
  rem = *timep % SECSPERDAY;
1444
9.72k
  while (tdays < 0 || tdays >= year_lengths[isleap(y)])
1445
4.86k
  {
1446
4.86k
    int     newy;
1447
4.86k
    pg_time_t tdelta;
1448
4.86k
    int     idelta;
1449
4.86k
    int     leapdays;
1450
1451
4.86k
    tdelta = tdays / DAYSPERLYEAR;
1452
4.86k
    if (!((!TYPE_SIGNED(pg_time_t) || INT_MIN <= tdelta)
1453
4.86k
        && tdelta <= INT_MAX))
1454
0
      goto out_of_range;
1455
4.86k
    idelta = tdelta;
1456
4.86k
    if (idelta == 0)
1457
4
      idelta = (tdays < 0) ? -1 : 1;
1458
4.86k
    newy = y;
1459
4.86k
    if (increment_overflow(&newy, idelta))
1460
0
      goto out_of_range;
1461
4.86k
    leapdays = leaps_thru_end_of(newy - 1) -
1462
4.86k
      leaps_thru_end_of(y - 1);
1463
4.86k
    tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
1464
4.86k
    tdays -= leapdays;
1465
4.86k
    y = newy;
1466
4.86k
  }
1467
1468
  /*
1469
   * Given the range, we can now fearlessly cast...
1470
   */
1471
4.85k
  idays = tdays;
1472
4.85k
  rem += offset - corr;
1473
4.85k
  while (rem < 0)
1474
0
  {
1475
0
    rem += SECSPERDAY;
1476
0
    --idays;
1477
0
  }
1478
4.85k
  while (rem >= SECSPERDAY)
1479
0
  {
1480
0
    rem -= SECSPERDAY;
1481
0
    ++idays;
1482
0
  }
1483
4.85k
  while (idays < 0)
1484
0
  {
1485
0
    if (increment_overflow(&y, -1))
1486
0
      goto out_of_range;
1487
0
    idays += year_lengths[isleap(y)];
1488
0
  }
1489
4.85k
  while (idays >= year_lengths[isleap(y)])
1490
0
  {
1491
0
    idays -= year_lengths[isleap(y)];
1492
0
    if (increment_overflow(&y, 1))
1493
0
      goto out_of_range;
1494
0
  }
1495
4.85k
  tmp->tm_year = y;
1496
4.85k
  if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1497
0
    goto out_of_range;
1498
4.85k
  tmp->tm_yday = idays;
1499
1500
  /*
1501
   * The "extra" mods below avoid overflow problems.
1502
   */
1503
4.85k
  tmp->tm_wday = EPOCH_WDAY +
1504
4.85k
    ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1505
4.85k
    (DAYSPERNYEAR % DAYSPERWEEK) +
1506
4.85k
    leaps_thru_end_of(y - 1) -
1507
4.85k
    leaps_thru_end_of(EPOCH_YEAR - 1) +
1508
4.85k
    idays;
1509
4.85k
  tmp->tm_wday %= DAYSPERWEEK;
1510
4.85k
  if (tmp->tm_wday < 0)
1511
0
    tmp->tm_wday += DAYSPERWEEK;
1512
4.85k
  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1513
4.85k
  rem %= SECSPERHOUR;
1514
4.85k
  tmp->tm_min = (int) (rem / SECSPERMIN);
1515
1516
  /*
1517
   * A positive leap second requires a special representation. This uses
1518
   * "... ??:59:60" et seq.
1519
   */
1520
4.85k
  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1521
4.85k
  ip = mon_lengths[isleap(y)];
1522
48.5k
  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1523
43.6k
    idays -= ip[tmp->tm_mon];
1524
4.85k
  tmp->tm_mday = (int) (idays + 1);
1525
4.85k
  tmp->tm_isdst = 0;
1526
4.85k
  tmp->tm_gmtoff = offset;
1527
4.85k
  return tmp;
1528
1529
0
out_of_range:
1530
0
  errno = EOVERFLOW;
1531
0
  return NULL;
1532
4.85k
}
1533
1534
/*
1535
 * Normalize logic courtesy Paul Eggert.
1536
 */
1537
1538
static bool
1539
increment_overflow(int *ip, int j)
1540
9.72k
{
1541
9.72k
  int const i = *ip;
1542
1543
  /*----------
1544
   * If i >= 0 there can only be overflow if i + j > INT_MAX
1545
   * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1546
   * If i < 0 there can only be overflow if i + j < INT_MIN
1547
   * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1548
   *----------
1549
   */
1550
9.72k
  if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1551
0
    return true;
1552
9.72k
  *ip += j;
1553
9.72k
  return false;
1554
9.72k
}
1555
1556
static bool
1557
increment_overflow_time(pg_time_t *tp, int32 j)
1558
0
{
1559
  /*----------
1560
   * This is like
1561
   * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1562
   * except that it does the right thing even if *tp + j would overflow.
1563
   *----------
1564
   */
1565
0
  if (!(j < 0
1566
0
      ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1567
0
      : *tp <= TIME_T_MAX - j))
1568
0
    return true;
1569
0
  *tp += j;
1570
0
  return false;
1571
0
}
1572
1573
static int64
1574
leapcorr(struct state const *sp, pg_time_t t)
1575
0
{
1576
0
  struct lsinfo const *lp;
1577
0
  int     i;
1578
1579
0
  i = sp->leapcnt;
1580
0
  while (--i >= 0)
1581
0
  {
1582
0
    lp = &sp->lsis[i];
1583
0
    if (t >= lp->ls_trans)
1584
0
      return lp->ls_corr;
1585
0
  }
1586
0
  return 0;
1587
0
}
1588
1589
/*
1590
 * Find the next DST transition time in the given zone after the given time
1591
 *
1592
 * *timep and *tz are input arguments, the other parameters are output values.
1593
 *
1594
 * When the function result is 1, *boundary is set to the pg_time_t
1595
 * representation of the next DST transition time after *timep,
1596
 * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
1597
 * state prevailing just before that boundary (in particular, the state
1598
 * prevailing at *timep), and *after_gmtoff and *after_isdst are set to
1599
 * the state prevailing just after that boundary.
1600
 *
1601
 * When the function result is 0, there is no known DST transition
1602
 * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
1603
 * offset and isdst state prevailing at *timep.  (This would occur in
1604
 * DST-less time zones, or if a zone has permanently ceased using DST.)
1605
 *
1606
 * A function result of -1 indicates failure (this case does not actually
1607
 * occur in our current implementation).
1608
 */
1609
int
1610
pg_next_dst_boundary(const pg_time_t *timep,
1611
           long int *before_gmtoff,
1612
           int *before_isdst,
1613
           pg_time_t *boundary,
1614
           long int *after_gmtoff,
1615
           int *after_isdst,
1616
           const pg_tz *tz)
1617
0
{
1618
0
  const struct state *sp;
1619
0
  const struct ttinfo *ttisp;
1620
0
  int     i;
1621
0
  int     j;
1622
0
  const pg_time_t t = *timep;
1623
1624
0
  sp = &tz->state;
1625
0
  if (sp->timecnt == 0)
1626
0
  {
1627
    /* non-DST zone, use the defaulttype */
1628
0
    ttisp = &sp->ttis[sp->defaulttype];
1629
0
    *before_gmtoff = ttisp->tt_utoff;
1630
0
    *before_isdst = ttisp->tt_isdst;
1631
0
    return 0;
1632
0
  }
1633
0
  if ((sp->goback && t < sp->ats[0]) ||
1634
0
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1635
0
  {
1636
    /* For values outside the transition table, extrapolate */
1637
0
    pg_time_t newt = t;
1638
0
    pg_time_t seconds;
1639
0
    pg_time_t tcycles;
1640
0
    int64   icycles;
1641
0
    int     result;
1642
1643
0
    if (t < sp->ats[0])
1644
0
      seconds = sp->ats[0] - t;
1645
0
    else
1646
0
      seconds = t - sp->ats[sp->timecnt - 1];
1647
0
    --seconds;
1648
0
    tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1649
0
    ++tcycles;
1650
0
    icycles = tcycles;
1651
0
    if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1652
0
      return -1;
1653
0
    seconds = icycles;
1654
0
    seconds *= YEARSPERREPEAT;
1655
0
    seconds *= AVGSECSPERYEAR;
1656
0
    if (t < sp->ats[0])
1657
0
      newt += seconds;
1658
0
    else
1659
0
      newt -= seconds;
1660
0
    if (newt < sp->ats[0] ||
1661
0
      newt > sp->ats[sp->timecnt - 1])
1662
0
      return -1;     /* "cannot happen" */
1663
1664
0
    result = pg_next_dst_boundary(&newt, before_gmtoff,
1665
0
                    before_isdst,
1666
0
                    boundary,
1667
0
                    after_gmtoff,
1668
0
                    after_isdst,
1669
0
                    tz);
1670
0
    if (t < sp->ats[0])
1671
0
      *boundary -= seconds;
1672
0
    else
1673
0
      *boundary += seconds;
1674
0
    return result;
1675
0
  }
1676
1677
0
  if (t >= sp->ats[sp->timecnt - 1])
1678
0
  {
1679
    /* No known transition > t, so use last known segment's type */
1680
0
    i = sp->types[sp->timecnt - 1];
1681
0
    ttisp = &sp->ttis[i];
1682
0
    *before_gmtoff = ttisp->tt_utoff;
1683
0
    *before_isdst = ttisp->tt_isdst;
1684
0
    return 0;
1685
0
  }
1686
0
  if (t < sp->ats[0])
1687
0
  {
1688
    /* For "before", use the defaulttype */
1689
0
    ttisp = &sp->ttis[sp->defaulttype];
1690
0
    *before_gmtoff = ttisp->tt_utoff;
1691
0
    *before_isdst = ttisp->tt_isdst;
1692
0
    *boundary = sp->ats[0];
1693
    /* And for "after", use the first segment's type */
1694
0
    i = sp->types[0];
1695
0
    ttisp = &sp->ttis[i];
1696
0
    *after_gmtoff = ttisp->tt_utoff;
1697
0
    *after_isdst = ttisp->tt_isdst;
1698
0
    return 1;
1699
0
  }
1700
  /* Else search to find the boundary following t */
1701
0
  {
1702
0
    int     lo = 1;
1703
0
    int     hi = sp->timecnt - 1;
1704
1705
0
    while (lo < hi)
1706
0
    {
1707
0
      int     mid = (lo + hi) >> 1;
1708
1709
0
      if (t < sp->ats[mid])
1710
0
        hi = mid;
1711
0
      else
1712
0
        lo = mid + 1;
1713
0
    }
1714
0
    i = lo;
1715
0
  }
1716
0
  j = sp->types[i - 1];
1717
0
  ttisp = &sp->ttis[j];
1718
0
  *before_gmtoff = ttisp->tt_utoff;
1719
0
  *before_isdst = ttisp->tt_isdst;
1720
0
  *boundary = sp->ats[i];
1721
0
  j = sp->types[i];
1722
0
  ttisp = &sp->ttis[j];
1723
0
  *after_gmtoff = ttisp->tt_utoff;
1724
0
  *after_isdst = ttisp->tt_isdst;
1725
0
  return 1;
1726
0
}
1727
1728
/*
1729
 * Identify a timezone abbreviation's meaning in the given zone
1730
 *
1731
 * Determine the GMT offset and DST flag associated with the abbreviation.
1732
 * This is generally used only when the abbreviation has actually changed
1733
 * meaning over time; therefore, we also take a UTC cutoff time, and return
1734
 * the meaning in use at or most recently before that time, or the meaning
1735
 * in first use after that time if the abbrev was never used before that.
1736
 *
1737
 * On success, returns true and sets *gmtoff and *isdst.  If the abbreviation
1738
 * was never used at all in this zone, returns false.
1739
 *
1740
 * Note: abbrev is matched case-sensitively; it should be all-upper-case.
1741
 */
1742
bool
1743
pg_interpret_timezone_abbrev(const char *abbrev,
1744
               const pg_time_t *timep,
1745
               long int *gmtoff,
1746
               int *isdst,
1747
               const pg_tz *tz)
1748
0
{
1749
0
  const struct state *sp;
1750
0
  const char *abbrs;
1751
0
  const struct ttinfo *ttisp;
1752
0
  int     abbrind;
1753
0
  int     cutoff;
1754
0
  int     i;
1755
0
  const pg_time_t t = *timep;
1756
1757
0
  sp = &tz->state;
1758
1759
  /*
1760
   * Locate the abbreviation in the zone's abbreviation list.  We assume
1761
   * there are not duplicates in the list.
1762
   */
1763
0
  abbrs = sp->chars;
1764
0
  abbrind = 0;
1765
0
  while (abbrind < sp->charcnt)
1766
0
  {
1767
0
    if (strcmp(abbrev, abbrs + abbrind) == 0)
1768
0
      break;
1769
0
    while (abbrs[abbrind] != '\0')
1770
0
      abbrind++;
1771
0
    abbrind++;
1772
0
  }
1773
0
  if (abbrind >= sp->charcnt)
1774
0
    return false;     /* not there! */
1775
1776
  /*
1777
   * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1778
   * (goback/goahead zones).  Finding the newest or oldest meaning of the
1779
   * abbreviation should get us what we want, since extrapolation would just
1780
   * be repeating the newest or oldest meanings.
1781
   *
1782
   * Use binary search to locate the first transition > cutoff time.  (Note
1783
   * that sp->timecnt could be zero, in which case this loop does nothing
1784
   * and only the defaulttype entry will be checked.)
1785
   */
1786
0
  {
1787
0
    int     lo = 0;
1788
0
    int     hi = sp->timecnt;
1789
1790
0
    while (lo < hi)
1791
0
    {
1792
0
      int     mid = (lo + hi) >> 1;
1793
1794
0
      if (t < sp->ats[mid])
1795
0
        hi = mid;
1796
0
      else
1797
0
        lo = mid + 1;
1798
0
    }
1799
0
    cutoff = lo;
1800
0
  }
1801
1802
  /*
1803
   * Scan backwards to find the latest interval using the given abbrev
1804
   * before the cutoff time.
1805
   */
1806
0
  for (i = cutoff - 1; i >= 0; i--)
1807
0
  {
1808
0
    ttisp = &sp->ttis[sp->types[i]];
1809
0
    if (ttisp->tt_desigidx == abbrind)
1810
0
    {
1811
0
      *gmtoff = ttisp->tt_utoff;
1812
0
      *isdst = ttisp->tt_isdst;
1813
0
      return true;
1814
0
    }
1815
0
  }
1816
1817
  /*
1818
   * Not found yet; check the defaulttype, which is notionally the era
1819
   * before any of the entries in sp->types[].
1820
   */
1821
0
  ttisp = &sp->ttis[sp->defaulttype];
1822
0
  if (ttisp->tt_desigidx == abbrind)
1823
0
  {
1824
0
    *gmtoff = ttisp->tt_utoff;
1825
0
    *isdst = ttisp->tt_isdst;
1826
0
    return true;
1827
0
  }
1828
1829
  /*
1830
   * Not there, so scan forwards to find the first one after the cutoff.
1831
   */
1832
0
  for (i = cutoff; i < sp->timecnt; i++)
1833
0
  {
1834
0
    ttisp = &sp->ttis[sp->types[i]];
1835
0
    if (ttisp->tt_desigidx == abbrind)
1836
0
    {
1837
0
      *gmtoff = ttisp->tt_utoff;
1838
0
      *isdst = ttisp->tt_isdst;
1839
0
      return true;
1840
0
    }
1841
0
  }
1842
1843
0
  return false;       /* hm, not actually used in any interval? */
1844
0
}
1845
1846
/*
1847
 * Detect whether a timezone abbreviation is defined within the given zone.
1848
 *
1849
 * This is similar to pg_interpret_timezone_abbrev() but is not concerned
1850
 * with a specific point in time.  We want to know if the abbreviation is
1851
 * known at all, and if so whether it has one meaning or several.
1852
 *
1853
 * Returns true if the abbreviation is known, false if not.
1854
 * If the abbreviation is known and has a single meaning (only one value
1855
 * of gmtoff/isdst), sets *isfixed = true and sets *gmtoff and *isdst.
1856
 * If there are multiple meanings, sets *isfixed = false.
1857
 *
1858
 * Note: abbrev is matched case-sensitively; it should be all-upper-case.
1859
 */
1860
bool
1861
pg_timezone_abbrev_is_known(const char *abbrev,
1862
              bool *isfixed,
1863
              long int *gmtoff,
1864
              int *isdst,
1865
              const pg_tz *tz)
1866
0
{
1867
0
  bool    result = false;
1868
0
  const struct state *sp = &tz->state;
1869
0
  const char *abbrs;
1870
0
  int     abbrind;
1871
1872
  /*
1873
   * Locate the abbreviation in the zone's abbreviation list.  We assume
1874
   * there are not duplicates in the list.
1875
   */
1876
0
  abbrs = sp->chars;
1877
0
  abbrind = 0;
1878
0
  while (abbrind < sp->charcnt)
1879
0
  {
1880
0
    if (strcmp(abbrev, abbrs + abbrind) == 0)
1881
0
      break;
1882
0
    while (abbrs[abbrind] != '\0')
1883
0
      abbrind++;
1884
0
    abbrind++;
1885
0
  }
1886
0
  if (abbrind >= sp->charcnt)
1887
0
    return false;     /* definitely not there */
1888
1889
  /*
1890
   * Scan the ttinfo array to find uses of the abbreviation.
1891
   */
1892
0
  for (int i = 0; i < sp->typecnt; i++)
1893
0
  {
1894
0
    const struct ttinfo *ttisp = &sp->ttis[i];
1895
1896
0
    if (ttisp->tt_desigidx == abbrind)
1897
0
    {
1898
0
      if (!result)
1899
0
      {
1900
        /* First usage */
1901
0
        *isfixed = true; /* for the moment */
1902
0
        *gmtoff = ttisp->tt_utoff;
1903
0
        *isdst = ttisp->tt_isdst;
1904
0
        result = true;
1905
0
      }
1906
0
      else
1907
0
      {
1908
        /* Second or later usage, does it match? */
1909
0
        if (*gmtoff != ttisp->tt_utoff ||
1910
0
          *isdst != ttisp->tt_isdst)
1911
0
        {
1912
0
          *isfixed = false;
1913
0
          break;    /* no point in looking further */
1914
0
        }
1915
0
      }
1916
0
    }
1917
0
  }
1918
1919
0
  return result;
1920
0
}
1921
1922
/*
1923
 * Iteratively fetch all the abbreviations used in the given time zone.
1924
 *
1925
 * *indx is a state counter that the caller must initialize to zero
1926
 * before the first call, and not touch between calls.
1927
 *
1928
 * Returns the next known abbreviation, or NULL if there are no more.
1929
 *
1930
 * Note: the caller typically applies pg_interpret_timezone_abbrev()
1931
 * to each result.  While that nominally results in O(N^2) time spent
1932
 * searching the sp->chars[] array, we don't expect any zone to have
1933
 * enough abbreviations to make that meaningful.
1934
 */
1935
const char *
1936
pg_get_next_timezone_abbrev(int *indx,
1937
              const pg_tz *tz)
1938
0
{
1939
0
  const char *result;
1940
0
  const struct state *sp = &tz->state;
1941
0
  const char *abbrs;
1942
0
  int     abbrind;
1943
1944
  /* If we're still in range, the result is the current abbrev. */
1945
0
  abbrs = sp->chars;
1946
0
  abbrind = *indx;
1947
0
  if (abbrind < 0 || abbrind >= sp->charcnt)
1948
0
    return NULL;
1949
0
  result = abbrs + abbrind;
1950
1951
  /* Advance *indx past this abbrev and its trailing null. */
1952
0
  while (abbrs[abbrind] != '\0')
1953
0
    abbrind++;
1954
0
  abbrind++;
1955
0
  *indx = abbrind;
1956
1957
0
  return result;
1958
0
}
1959
1960
/*
1961
 * If the given timezone uses only one GMT offset, store that offset
1962
 * into *gmtoff and return true, else return false.
1963
 */
1964
bool
1965
pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
1966
0
{
1967
  /*
1968
   * The zone could have more than one ttinfo, if it's historically used
1969
   * more than one abbreviation.  We return true as long as they all have
1970
   * the same gmtoff.
1971
   */
1972
0
  const struct state *sp;
1973
0
  int     i;
1974
1975
0
  sp = &tz->state;
1976
0
  for (i = 1; i < sp->typecnt; i++)
1977
0
  {
1978
0
    if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1979
0
      return false;
1980
0
  }
1981
0
  *gmtoff = sp->ttis[0].tt_utoff;
1982
0
  return true;
1983
0
}
1984
1985
/*
1986
 * Return the name of the current timezone
1987
 */
1988
const char *
1989
pg_get_timezone_name(pg_tz *tz)
1990
0
{
1991
0
  if (tz)
1992
0
    return tz->TZname;
1993
0
  return NULL;
1994
0
}
1995
1996
/*
1997
 * Check whether timezone is acceptable.
1998
 *
1999
 * What we are doing here is checking for leap-second-aware timekeeping.
2000
 * We need to reject such TZ settings because they'll wreak havoc with our
2001
 * date/time arithmetic.
2002
 */
2003
bool
2004
pg_tz_acceptable(pg_tz *tz)
2005
4
{
2006
4
  struct pg_tm *tt;
2007
4
  pg_time_t time2000;
2008
2009
  /*
2010
   * To detect leap-second timekeeping, run pg_localtime for what should be
2011
   * GMT midnight, 2000-01-01.  Insist that the tm_sec value be zero; any
2012
   * other result has to be due to leap seconds.
2013
   */
2014
4
  time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
2015
4
  tt = pg_localtime(&time2000, tz);
2016
4
  if (!tt || tt->tm_sec != 0)
2017
0
    return false;
2018
2019
4
  return true;
2020
4
}