~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/timezone/localtime.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is in the public domain, so clarified as of
 
3
 * 1996-06-05 by Arthur David Olson.
 
4
 *
 
5
 * IDENTIFICATION
 
6
 *        $PostgreSQL$
 
7
 */
 
8
 
 
9
/*
 
10
 * Leap second handling from Bradley White.
 
11
 * POSIX-style TZ environment variable handling from Guy Harris.
 
12
 */
 
13
 
 
14
/* this file needs to build in both frontend and backend contexts */
 
15
#include "c.h"
 
16
 
 
17
#include <fcntl.h>
 
18
 
 
19
#include "private.h"
 
20
#include "pgtz.h"
 
21
#include "tzfile.h"
 
22
 
 
23
 
 
24
#ifndef WILDABBR
 
25
/*----------
 
26
 * Someone might make incorrect use of a time zone abbreviation:
 
27
 *      1.      They might reference tzname[0] before calling tzset (explicitly
 
28
 *              or implicitly).
 
29
 *      2.      They might reference tzname[1] before calling tzset (explicitly
 
30
 *              or implicitly).
 
31
 *      3.      They might reference tzname[1] after setting to a time zone
 
32
 *              in which Daylight Saving Time is never observed.
 
33
 *      4.      They might reference tzname[0] after setting to a time zone
 
34
 *              in which Standard Time is never observed.
 
35
 *      5.      They might reference tm.TM_ZONE after calling offtime.
 
36
 * What's best to do in the above cases is open to debate;
 
37
 * for now, we just set things up so that in any of the five cases
 
38
 * WILDABBR is used. Another possibility:       initialize tzname[0] to the
 
39
 * string "tzname[0] used before set", and similarly for the other cases.
 
40
 * And another: initialize tzname[0] to "ERA", with an explanation in the
 
41
 * manual page of what this "time zone abbreviation" means (doing this so
 
42
 * that tzname[0] has the "normal" length of three characters).
 
43
 *----------
 
44
 */
 
45
#define WILDABBR        "   "
 
46
#endif   /* !defined WILDABBR */
 
47
 
 
48
static char wildabbr[] = WILDABBR;
 
49
 
 
50
static const char gmt[] = "GMT";
 
51
 
 
52
/*
 
53
 * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
 
54
 * We default to US rules as of 1999-08-17.
 
55
 * POSIX 1003.1 section 8.1.1 says that the default DST rules are
 
56
 * implementation dependent; for historical reasons, US rules are a
 
57
 * common default.
 
58
 */
 
59
#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
 
60
 
 
61
struct rule
 
62
{
 
63
        int                     r_type;                 /* type of rule--see below */
 
64
        int                     r_day;                  /* day number of rule */
 
65
        int                     r_week;                 /* week number of rule */
 
66
        int                     r_mon;                  /* month number of rule */
 
67
        long            r_time;                 /* transition time of rule */
 
68
};
 
69
 
 
70
#define JULIAN_DAY              0               /* Jn - Julian day */
 
71
#define DAY_OF_YEAR             1               /* n - day of year */
 
72
#define MONTH_NTH_DAY_OF_WEEK   2               /* Mm.n.d - month, week, day of week */
 
73
 
 
74
/*
 
75
 * Prototypes for static functions.
 
76
 */
 
77
 
 
78
static long detzcode(const char *codep);
 
79
static pg_time_t detzcode64(const char *codep);
 
80
static int differ_by_repeat(pg_time_t t1, pg_time_t t0);
 
81
static const char *getzname(const char *strp);
 
82
static const char *getqzname(const char *strp, int delim);
 
83
static const char *getnum(const char *strp, int *nump, int min, int max);
 
84
static const char *getsecs(const char *strp, long *secsp);
 
85
static const char *getoffset(const char *strp, long *offsetp);
 
86
static const char *getrule(const char *strp, struct rule * rulep);
 
87
static void gmtload(struct state * sp);
 
88
static struct pg_tm *gmtsub(const pg_time_t *timep, long offset, 
 
89
                                                        struct pg_tm *tmp);
 
90
static struct pg_tm *localsub(const pg_time_t *timep, long offset, 
 
91
                                                           struct pg_tm *tmp, const pg_tz *tz);
 
92
static int increment_overflow(int *number, int delta);
 
93
static pg_time_t transtime(pg_time_t janfirst, int year,
 
94
                  const struct rule *rulep, long offset);
 
95
static int typesequiv(const struct state *sp, int a, int b);
 
96
static struct pg_tm *timesub(const pg_time_t *timep, long offset,
 
97
                                                         const struct state *sp, struct pg_tm *tmp);
 
98
 
 
99
/* GMT timezone */
 
100
static struct state gmtmem;
 
101
 
 
102
#define gmtptr          (&gmtmem)
 
103
 
 
104
 
 
105
static int      gmt_is_set = 0;
 
106
 
 
107
/*
 
108
 * Section 4.12.3 of X3.159-1989 requires that
 
109
 *      Except for the strftime function, these functions [asctime,
 
110
 *      ctime, gmtime, localtime] return values in one of two static
 
111
 *      objects: a broken-down time structure and an array of char.
 
112
 * Thanks to Paul Eggert for noting this.
 
113
 */
 
114
 
 
115
static struct pg_tm tm;
 
116
 
 
117
 
 
118
static long
 
119
detzcode(const char *codep)
 
120
{
 
121
        long            result;
 
122
        int                     i;
 
123
 
 
124
        result = (codep[0] & 0x80) ? ~0L : 0;
 
125
        for (i = 0; i < 4; ++i)
 
126
                result = (result << 8) | (codep[i] & 0xff);
 
127
        return result;
 
128
}
 
129
 
 
130
static pg_time_t
 
131
detzcode64(const char *codep)
 
132
{
 
133
        pg_time_t result;
 
134
        int    i;
 
135
 
 
136
        result = (codep[0] & 0x80) ?  (~(int64) 0) : 0;
 
137
        for (i = 0; i < 8; ++i)
 
138
                result = result * 256 + (codep[i] & 0xff);
 
139
        return result;
 
140
}
 
141
 
 
142
static int
 
143
differ_by_repeat(pg_time_t t1, pg_time_t t0)
 
144
{
 
145
        if (TYPE_INTEGRAL(pg_time_t) &&
 
146
                TYPE_BIT(pg_time_t) - TYPE_SIGNED(pg_time_t) < SECSPERREPEAT_BITS)
 
147
                return 0;
 
148
        return t1 - t0 == SECSPERREPEAT;
 
149
}
 
150
 
 
151
int
 
152
tzload(const char *name, char *canonname, struct state * sp, int doextend)
 
153
{
 
154
        const char *p;
 
155
        int                     i;
 
156
        int                     fid;
 
157
        int                     stored;
 
158
        int                     nread;
 
159
        union
 
160
        {
 
161
                struct tzhead tzhead;
 
162
                char            buf[2 * sizeof(struct tzhead) +
 
163
                                                2 * sizeof *sp +
 
164
                                                4 * TZ_MAX_TIMES];
 
165
        } u;
 
166
 
 
167
        if (name == NULL && (name = TZDEFAULT) == NULL)
 
168
                return -1;
 
169
        if (name[0] == ':')
 
170
                ++name;
 
171
        fid = pg_open_tzfile(name, canonname);
 
172
        if (fid < 0)
 
173
                return -1;
 
174
        nread = read(fid, u.buf, sizeof u.buf);
 
175
        if (close(fid) != 0 || nread <= 0)
 
176
                return -1;
 
177
        for (stored = 4; stored <= 8; stored *= 2)
 
178
        {
 
179
                int                     ttisstdcnt;
 
180
                int                     ttisgmtcnt;
 
181
 
 
182
                ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
 
183
                ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
 
184
                sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
 
185
                sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
 
186
                sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
 
187
                sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
 
188
                p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
 
189
                if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
 
190
                        sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
 
191
                        sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
 
192
                        sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
 
193
                        (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
 
194
                        (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
 
195
                        return -1;
 
196
                if (nread - (p - u.buf) <
 
197
                        sp->timecnt * stored + /* ats */
 
198
                        sp->timecnt +           /* types */
 
199
                        sp->typecnt * 6 +               /* ttinfos */
 
200
                        sp->charcnt +           /* chars */
 
201
                        sp->leapcnt * (stored + 4) +            /* lsinfos */
 
202
                        ttisstdcnt +            /* ttisstds */
 
203
                        ttisgmtcnt)                     /* ttisgmts */
 
204
                        return -1;
 
205
                for (i = 0; i < sp->timecnt; ++i)
 
206
                {
 
207
                        sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p);
 
208
                        p += stored;
 
209
                }
 
210
                for (i = 0; i < sp->timecnt; ++i)
 
211
                {
 
212
                        sp->types[i] = (unsigned char) *p++;
 
213
                        if (sp->types[i] >= sp->typecnt)
 
214
                                return -1;
 
215
                }
 
216
                for (i = 0; i < sp->typecnt; ++i)
 
217
                {
 
218
                        struct ttinfo *ttisp;
 
219
 
 
220
                        ttisp = &sp->ttis[i];
 
221
                        ttisp->tt_gmtoff = detzcode(p);
 
222
                        p += 4;
 
223
                        ttisp->tt_isdst = (unsigned char) *p++;
 
224
                        if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
 
225
                                return -1;
 
226
                        ttisp->tt_abbrind = (unsigned char) *p++;
 
227
                        if (ttisp->tt_abbrind < 0 ||
 
228
                                ttisp->tt_abbrind > sp->charcnt)
 
229
                                return -1;
 
230
                }
 
231
                for (i = 0; i < sp->charcnt; ++i)
 
232
                        sp->chars[i] = *p++;
 
233
                sp->chars[i] = '\0';    /* ensure '\0' at end */
 
234
                for (i = 0; i < sp->leapcnt; ++i)
 
235
                {
 
236
                        struct lsinfo *lsisp;
 
237
 
 
238
                        lsisp = &sp->lsis[i];
 
239
                        lsisp->ls_trans = (stored == 4) ? detzcode(p) : detzcode64(p);
 
240
                        p += stored;
 
241
                        lsisp->ls_corr = detzcode(p);
 
242
                        p += 4;
 
243
                }
 
244
                for (i = 0; i < sp->typecnt; ++i)
 
245
                {
 
246
                        struct ttinfo *ttisp;
 
247
 
 
248
                        ttisp = &sp->ttis[i];
 
249
                        if (ttisstdcnt == 0)
 
250
                                ttisp->tt_ttisstd = FALSE;
 
251
                        else
 
252
                        {
 
253
                                ttisp->tt_ttisstd = *p++;
 
254
                                if (ttisp->tt_ttisstd != TRUE &&
 
255
                                        ttisp->tt_ttisstd != FALSE)
 
256
                                        return -1;
 
257
                        }
 
258
                }
 
259
                for (i = 0; i < sp->typecnt; ++i)
 
260
                {
 
261
                        struct ttinfo *ttisp;
 
262
 
 
263
                        ttisp = &sp->ttis[i];
 
264
                        if (ttisgmtcnt == 0)
 
265
                                ttisp->tt_ttisgmt = FALSE;
 
266
                        else
 
267
                        {
 
268
                                ttisp->tt_ttisgmt = *p++;
 
269
                                if (ttisp->tt_ttisgmt != TRUE &&
 
270
                                        ttisp->tt_ttisgmt != FALSE)
 
271
                                        return -1;
 
272
                        }
 
273
                }
 
274
                /*
 
275
                 * Out-of-sort ats should mean we're running on a
 
276
                 * signed time_t system but using a data file with
 
277
                 * unsigned values (or vice versa).
 
278
                 */
 
279
                for (i = 0; i < sp->timecnt - 2; ++i)
 
280
                        if (sp->ats[i] > sp->ats[i + 1])
 
281
                        {
 
282
                                ++i;
 
283
                                if (TYPE_SIGNED(pg_time_t))
 
284
                                {
 
285
                                        /*
 
286
                                         * Ignore the end (easy).
 
287
                                         */
 
288
                                        sp->timecnt = i;
 
289
                                }
 
290
                                else
 
291
                                {
 
292
                                        /*
 
293
                                         * Ignore the beginning (harder).
 
294
                                         */
 
295
                                        int j;
 
296
                                        
 
297
                                        for (j = 0; j + i < sp->timecnt; ++j)
 
298
                                        {
 
299
                                                sp->ats[j] = sp->ats[j + i];
 
300
                                                sp->types[j] = sp->types[j + i];
 
301
                                        }
 
302
                                        sp->timecnt = j;
 
303
                                }
 
304
                                break;
 
305
                        }
 
306
                /*
 
307
                 * If this is an old file, we're done.
 
308
                 */
 
309
                if (u.tzhead.tzh_version[0] == '\0')
 
310
                        break;
 
311
                nread -= p - u.buf;
 
312
                for (i = 0; i < nread; ++i)
 
313
                        u.buf[i] = p[i];
 
314
                /*
 
315
                 * If this is a narrow integer time_t system, we're done.
 
316
                 */
 
317
                if (stored >= (int) sizeof(pg_time_t) && TYPE_INTEGRAL(pg_time_t))
 
318
                        break;
 
319
        }
 
320
        if (doextend && nread > 2 &&
 
321
                u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
 
322
                sp->typecnt + 2 <= TZ_MAX_TYPES)
 
323
        {
 
324
                struct state    ts;
 
325
                int    result;
 
326
 
 
327
                u.buf[nread - 1] = '\0';
 
328
                result = tzparse(&u.buf[1], &ts, FALSE);
 
329
                if (result == 0 && ts.typecnt == 2 &&
 
330
                        sp->charcnt + ts.charcnt <= TZ_MAX_CHARS)
 
331
                {
 
332
                        for (i = 0; i < 2; ++i)
 
333
                                ts.ttis[i].tt_abbrind +=
 
334
                                        sp->charcnt;
 
335
                        for (i = 0; i < ts.charcnt; ++i)
 
336
                                sp->chars[sp->charcnt++] =
 
337
                                        ts.chars[i];
 
338
                        i = 0;
 
339
                        while (i < ts.timecnt &&
 
340
                                   ts.ats[i] <=
 
341
                                   sp->ats[sp->timecnt - 1])
 
342
                                ++i;
 
343
                        while (i < ts.timecnt &&
 
344
                                   sp->timecnt < TZ_MAX_TIMES)
 
345
                        {
 
346
                                sp->ats[sp->timecnt] =
 
347
                                        ts.ats[i];
 
348
                                sp->types[sp->timecnt] =
 
349
                                        sp->typecnt +
 
350
                                        ts.types[i];
 
351
                                ++sp->timecnt;
 
352
                                ++i;
 
353
                        }
 
354
                        sp->ttis[sp->typecnt++] = ts.ttis[0];
 
355
                        sp->ttis[sp->typecnt++] = ts.ttis[1];
 
356
                }
 
357
        }
 
358
        i = 2 * YEARSPERREPEAT;
 
359
        sp->goback = sp->goahead = sp->timecnt > i;
 
360
        sp->goback = sp->goback &&
 
361
                typesequiv(sp, sp->types[i], sp->types[0]) &&
 
362
                differ_by_repeat(sp->ats[i], sp->ats[0]);
 
363
        sp->goahead = sp->goahead &&
 
364
                typesequiv(sp, sp->types[sp->timecnt - 1],
 
365
                                   sp->types[sp->timecnt - 1 - i]) &&
 
366
                differ_by_repeat(sp->ats[sp->timecnt - 1],
 
367
                                                 sp->ats[sp->timecnt - 1 - i]);
 
368
        return 0;
 
369
}
 
370
 
 
371
static int
 
372
typesequiv(const struct state *sp, int a, int b)
 
373
{
 
374
        int    result;
 
375
 
 
376
        if (sp == NULL ||
 
377
                a < 0 || a >= sp->typecnt ||
 
378
                b < 0 || b >= sp->typecnt)
 
379
                result = FALSE;
 
380
        else
 
381
        {
 
382
                const struct ttinfo *ap = &sp->ttis[a];
 
383
                const struct ttinfo *bp = &sp->ttis[b];
 
384
 
 
385
                result = ap->tt_gmtoff == bp->tt_gmtoff &&
 
386
                        ap->tt_isdst == bp->tt_isdst &&
 
387
                        ap->tt_ttisstd == bp->tt_ttisstd &&
 
388
                        ap->tt_ttisgmt == bp->tt_ttisgmt &&
 
389
                        strcmp(&sp->chars[ap->tt_abbrind],
 
390
                                   &sp->chars[bp->tt_abbrind]) == 0;
 
391
        }
 
392
        return result;
 
393
}
 
394
 
 
395
static const int mon_lengths[2][MONSPERYEAR] = {
 
396
        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 
397
        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
 
398
};
 
399
 
 
400
static const int year_lengths[2] = {
 
401
        DAYSPERNYEAR, DAYSPERLYEAR
 
402
};
 
403
 
 
404
/*
 
405
 * Given a pointer into a time zone string, scan until a character that is not
 
406
 * a valid character in a zone name is found. Return a pointer to that
 
407
 * character.
 
408
 */
 
409
static const char *
 
410
getzname(const char *strp)
 
411
{
 
412
        char            c;
 
413
 
 
414
        while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
 
415
                   c != '+')
 
416
                ++strp;
 
417
        return strp;
 
418
}
 
419
 
 
420
/*
 
421
 * Given a pointer into an extended time zone string, scan until the ending
 
422
 * delimiter of the zone name is located. Return a pointer to the delimiter.
 
423
 *
 
424
 * As with getzname above, the legal character set is actually quite
 
425
 * restricted, with other characters producing undefined results.
 
426
 * We don't do any checking here; checking is done later in common-case code.
 
427
 */
 
428
static const char *
 
429
getqzname(const char *strp, int delim)
 
430
{
 
431
        int    c;
 
432
 
 
433
        while ((c = *strp) != '\0' && c != delim)
 
434
                ++strp;
 
435
        return strp;
 
436
}
 
437
 
 
438
/*
 
439
 * Given a pointer into a time zone string, extract a number from that string.
 
440
 * Check that the number is within a specified range; if it is not, return
 
441
 * NULL.
 
442
 * Otherwise, return a pointer to the first character not part of the number.
 
443
 */
 
444
static const char *
 
445
getnum(const char *strp, int *nump, int min, int max)
 
446
{
 
447
        char            c;
 
448
        int                     num;
 
449
 
 
450
        if (strp == NULL || !is_digit(c = *strp))
 
451
                return NULL;
 
452
        num = 0;
 
453
        do
 
454
        {
 
455
                num = num * 10 + (c - '0');
 
456
                if (num > max)
 
457
                        return NULL;            /* illegal value */
 
458
                c = *++strp;
 
459
        } while (is_digit(c));
 
460
        if (num < min)
 
461
                return NULL;                    /* illegal value */
 
462
        *nump = num;
 
463
        return strp;
 
464
}
 
465
 
 
466
/*
 
467
 * Given a pointer into a time zone string, extract a number of seconds,
 
468
 * in hh[:mm[:ss]] form, from the string.
 
469
 * If any error occurs, return NULL.
 
470
 * Otherwise, return a pointer to the first character not part of the number
 
471
 * of seconds.
 
472
 */
 
473
static const char *
 
474
getsecs(const char *strp, long *secsp)
 
475
{
 
476
        int                     num;
 
477
 
 
478
        /*
 
479
         * `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
 
480
         * "M10.4.6/26", which does not conform to Posix, but which specifies the
 
481
         * equivalent of ``02:00 on the first Sunday on or after 23 Oct''.
 
482
         */
 
483
        strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
 
484
        if (strp == NULL)
 
485
                return NULL;
 
486
        *secsp = num * (long) SECSPERHOUR;
 
487
        if (*strp == ':')
 
488
        {
 
489
                ++strp;
 
490
                strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
 
491
                if (strp == NULL)
 
492
                        return NULL;
 
493
                *secsp += num * SECSPERMIN;
 
494
                if (*strp == ':')
 
495
                {
 
496
                        ++strp;
 
497
                        /* `SECSPERMIN' allows for leap seconds. */
 
498
                        strp = getnum(strp, &num, 0, SECSPERMIN);
 
499
                        if (strp == NULL)
 
500
                                return NULL;
 
501
                        *secsp += num;
 
502
                }
 
503
        }
 
504
        return strp;
 
505
}
 
506
 
 
507
/*
 
508
 * Given a pointer into a time zone string, extract an offset, in
 
509
 * [+-]hh[:mm[:ss]] form, from the string.
 
510
 * If any error occurs, return NULL.
 
511
 * Otherwise, return a pointer to the first character not part of the time.
 
512
 */
 
513
static const char *
 
514
getoffset(const char *strp, long *offsetp)
 
515
{
 
516
        int                     neg = 0;
 
517
 
 
518
        if (*strp == '-')
 
519
        {
 
520
                neg = 1;
 
521
                ++strp;
 
522
        }
 
523
        else if (*strp == '+')
 
524
                ++strp;
 
525
        strp = getsecs(strp, offsetp);
 
526
        if (strp == NULL)
 
527
                return NULL;                    /* illegal time */
 
528
        if (neg)
 
529
                *offsetp = -*offsetp;
 
530
        return strp;
 
531
}
 
532
 
 
533
/*
 
534
 * Given a pointer into a time zone string, extract a rule in the form
 
535
 * date[/time]. See POSIX section 8 for the format of "date" and "time".
 
536
 * If a valid rule is not found, return NULL.
 
537
 * Otherwise, return a pointer to the first character not part of the rule.
 
538
 */
 
539
static const char *
 
540
getrule(const char *strp, struct rule * rulep)
 
541
{
 
542
        if (*strp == 'J')
 
543
        {
 
544
                /*
 
545
                 * Julian day.
 
546
                 */
 
547
                rulep->r_type = JULIAN_DAY;
 
548
                ++strp;
 
549
                strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
 
550
        }
 
551
        else if (*strp == 'M')
 
552
        {
 
553
                /*
 
554
                 * Month, week, day.
 
555
                 */
 
556
                rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
 
557
                ++strp;
 
558
                strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
 
559
                if (strp == NULL)
 
560
                        return NULL;
 
561
                if (*strp++ != '.')
 
562
                        return NULL;
 
563
                strp = getnum(strp, &rulep->r_week, 1, 5);
 
564
                if (strp == NULL)
 
565
                        return NULL;
 
566
                if (*strp++ != '.')
 
567
                        return NULL;
 
568
                strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
 
569
        }
 
570
        else if (is_digit(*strp))
 
571
        {
 
572
                /*
 
573
                 * Day of year.
 
574
                 */
 
575
                rulep->r_type = DAY_OF_YEAR;
 
576
                strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
 
577
        }
 
578
        else
 
579
                return NULL;                    /* invalid format */
 
580
        if (strp == NULL)
 
581
                return NULL;
 
582
        if (*strp == '/')
 
583
        {
 
584
                /*
 
585
                 * Time specified.
 
586
                 */
 
587
                ++strp;
 
588
                strp = getsecs(strp, &rulep->r_time);
 
589
        }
 
590
        else
 
591
                rulep->r_time = 2 * SECSPERHOUR;                /* default = 2:00:00 */
 
592
        return strp;
 
593
}
 
594
 
 
595
/*
 
596
 * Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
 
597
 * year, a rule, and the offset from UTC at the time that rule takes effect,
 
598
 * calculate the Epoch-relative time that rule takes effect.
 
599
 */
 
600
static pg_time_t
 
601
transtime(pg_time_t janfirst, int year,
 
602
                  const struct rule * rulep, long offset)
 
603
{
 
604
        int                     leapyear;
 
605
        pg_time_t       value = 0;
 
606
        int                     i,
 
607
                                d,
 
608
                                m1,
 
609
                                yy0,
 
610
                                yy1,
 
611
                                yy2,
 
612
                                dow;
 
613
 
 
614
        leapyear = isleap(year);
 
615
        switch (rulep->r_type)
 
616
        {
 
617
 
 
618
                case JULIAN_DAY:
 
619
 
 
620
                        /*
 
621
                         * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
 
622
                         * years. In non-leap years, or if the day number is 59 or less,
 
623
                         * just add SECSPERDAY times the day number-1 to the time of
 
624
                         * January 1, midnight, to get the day.
 
625
                         */
 
626
                        value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
 
627
                        if (leapyear && rulep->r_day >= 60)
 
628
                                value += SECSPERDAY;
 
629
                        break;
 
630
 
 
631
                case DAY_OF_YEAR:
 
632
 
 
633
                        /*
 
634
                         * n - day of year. Just add SECSPERDAY times the day number to
 
635
                         * the time of January 1, midnight, to get the day.
 
636
                         */
 
637
                        value = janfirst + rulep->r_day * SECSPERDAY;
 
638
                        break;
 
639
 
 
640
                case MONTH_NTH_DAY_OF_WEEK:
 
641
 
 
642
                        /*
 
643
                         * Mm.n.d - nth "dth day" of month m.
 
644
                         */
 
645
                        value = janfirst;
 
646
                        for (i = 0; i < rulep->r_mon - 1; ++i)
 
647
                                value += mon_lengths[leapyear][i] * SECSPERDAY;
 
648
 
 
649
                        /*
 
650
                         * Use Zeller's Congruence to get day-of-week of first day of
 
651
                         * month.
 
652
                         */
 
653
                        m1 = (rulep->r_mon + 9) % 12 + 1;
 
654
                        yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
 
655
                        yy1 = yy0 / 100;
 
656
                        yy2 = yy0 % 100;
 
657
                        dow = ((26 * m1 - 2) / 10 +
 
658
                                   1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
 
659
                        if (dow < 0)
 
660
                                dow += DAYSPERWEEK;
 
661
 
 
662
                        /*
 
663
                         * "dow" is the day-of-week of the first day of the month. Get the
 
664
                         * day-of-month (zero-origin) of the first "dow" day of the month.
 
665
                         */
 
666
                        d = rulep->r_day - dow;
 
667
                        if (d < 0)
 
668
                                d += DAYSPERWEEK;
 
669
                        for (i = 1; i < rulep->r_week; ++i)
 
670
                        {
 
671
                                if (d + DAYSPERWEEK >=
 
672
                                        mon_lengths[leapyear][rulep->r_mon - 1])
 
673
                                        break;
 
674
                                d += DAYSPERWEEK;
 
675
                        }
 
676
 
 
677
                        /*
 
678
                         * "d" is the day-of-month (zero-origin) of the day we want.
 
679
                         */
 
680
                        value += d * SECSPERDAY;
 
681
                        break;
 
682
        }
 
683
 
 
684
        /*
 
685
         * "value" is the Epoch-relative time of 00:00:00 UTC on the day in
 
686
         * question.  To get the Epoch-relative time of the specified local time
 
687
         * on that day, add the transition time and the current offset from UTC.
 
688
         */
 
689
        return value + rulep->r_time + offset;
 
690
}
 
691
 
 
692
/*
 
693
 * Given a POSIX section 8-style TZ string, fill in the rule tables as
 
694
 * appropriate.
 
695
 */
 
696
 
 
697
int
 
698
tzparse(const char *name, struct state * sp, int lastditch)
 
699
{
 
700
        const char *stdname;
 
701
        const char *dstname = NULL;
 
702
        size_t          stdlen;
 
703
        size_t          dstlen;
 
704
        long            stdoffset;
 
705
        long            dstoffset;
 
706
        pg_time_t  *atp;
 
707
        unsigned char *typep;
 
708
        char       *cp;
 
709
        int                     load_result;
 
710
 
 
711
        stdname = name;
 
712
        if (lastditch)
 
713
        {
 
714
                stdlen = strlen(name);  /* length of standard zone name */
 
715
                name += stdlen;
 
716
                if (stdlen >= sizeof sp->chars)
 
717
                        stdlen = (sizeof sp->chars) - 1;
 
718
                stdoffset = 0;
 
719
 
 
720
                /*
 
721
                 * Unlike the original zic library, do NOT invoke tzload() here; we
 
722
                 * can't assume pg_open_tzfile() is sane yet, and we don't care about
 
723
                 * leap seconds anyway.
 
724
                 */
 
725
                load_result = -1;
 
726
        }
 
727
        else
 
728
        {
 
729
                if (*name == '<')
 
730
                {
 
731
                        name++;
 
732
                        stdname = name;
 
733
                        name = getqzname(name, '>');
 
734
                        if (*name != '>')
 
735
                                return (-1);
 
736
                        stdlen = name - stdname;
 
737
                        name++;
 
738
                }
 
739
                else
 
740
                {
 
741
                        name = getzname(name);
 
742
                        stdlen = name - stdname;
 
743
                }
 
744
                if (*name == '\0')
 
745
                        return -1;
 
746
                name = getoffset(name, &stdoffset);
 
747
                if (name == NULL)
 
748
                        return -1;
 
749
                load_result = tzload(TZDEFRULES, NULL, sp, FALSE);
 
750
        }
 
751
        if (load_result != 0)
 
752
                sp->leapcnt = 0;                /* so, we're off a little */
 
753
        if (*name != '\0')
 
754
        {
 
755
                if (*name == '<')
 
756
                {
 
757
                        dstname = ++name;
 
758
                        name = getqzname(name, '>');
 
759
                        if (*name != '>')
 
760
                                return -1;
 
761
                        dstlen = name - dstname;
 
762
                        name++;
 
763
                }
 
764
                else
 
765
                {
 
766
                        dstname = name;
 
767
                        name = getzname(name);
 
768
                        dstlen = name - dstname;        /* length of DST zone name */
 
769
                }
 
770
                if (*name != '\0' && *name != ',' && *name != ';')
 
771
                {
 
772
                        name = getoffset(name, &dstoffset);
 
773
                        if (name == NULL)
 
774
                                return -1;
 
775
                }
 
776
                else
 
777
                        dstoffset = stdoffset - SECSPERHOUR;
 
778
                if (*name == '\0' && load_result != 0)
 
779
                        name = TZDEFRULESTRING;
 
780
                if (*name == ',' || *name == ';')
 
781
                {
 
782
                        struct rule start;
 
783
                        struct rule end;
 
784
                        int                     year;
 
785
                        pg_time_t       janfirst;
 
786
                        pg_time_t       starttime;
 
787
                        pg_time_t       endtime;
 
788
 
 
789
                        ++name;
 
790
                        if ((name = getrule(name, &start)) == NULL)
 
791
                                return -1;
 
792
                        if (*name++ != ',')
 
793
                                return -1;
 
794
                        if ((name = getrule(name, &end)) == NULL)
 
795
                                return -1;
 
796
                        if (*name != '\0')
 
797
                                return -1;
 
798
                        sp->typecnt = 2;        /* standard time and DST */
 
799
 
 
800
                        /*
 
801
                         * Two transitions per year, from EPOCH_YEAR forward.
 
802
                         */
 
803
                        sp->ttis[0].tt_gmtoff = -dstoffset;
 
804
                        sp->ttis[0].tt_isdst = 1;
 
805
                        sp->ttis[0].tt_abbrind = stdlen + 1;
 
806
                        sp->ttis[1].tt_gmtoff = -stdoffset;
 
807
                        sp->ttis[1].tt_isdst = 0;
 
808
                        sp->ttis[1].tt_abbrind = 0;
 
809
                        atp = sp->ats;
 
810
                        typep = sp->types;
 
811
                        janfirst = 0;
 
812
                        sp->timecnt = 0;
 
813
                        for (year = EPOCH_YEAR;
 
814
                                 sp->timecnt + 2 <= TZ_MAX_TIMES;
 
815
                                 ++year)
 
816
                        {
 
817
                                pg_time_t newfirst;
 
818
 
 
819
                                starttime = transtime(janfirst, year, &start,
 
820
                                                                          stdoffset);
 
821
                                endtime = transtime(janfirst, year, &end,
 
822
                                                                        dstoffset);
 
823
                                if (starttime > endtime)
 
824
                                {
 
825
                                        *atp++ = endtime;
 
826
                                        *typep++ = 1;           /* DST ends */
 
827
                                        *atp++ = starttime;
 
828
                                        *typep++ = 0;           /* DST begins */
 
829
                                }
 
830
                                else
 
831
                                {
 
832
                                        *atp++ = starttime;
 
833
                                        *typep++ = 0;           /* DST begins */
 
834
                                        *atp++ = endtime;
 
835
                                        *typep++ = 1;           /* DST ends */
 
836
                                }
 
837
                                sp->timecnt += 2;
 
838
                                newfirst = janfirst;
 
839
                                newfirst += year_lengths[isleap(year)] *
 
840
                                        SECSPERDAY;
 
841
                                if (newfirst <= janfirst)
 
842
                                        break;
 
843
                                janfirst = newfirst;
 
844
                        }
 
845
                }
 
846
                else
 
847
                {
 
848
                        long            theirstdoffset;
 
849
                        long            theirdstoffset;
 
850
                        long            theiroffset;
 
851
                        int                     isdst;
 
852
                        int                     i;
 
853
                        int                     j;
 
854
 
 
855
                        if (*name != '\0')
 
856
                                return -1;
 
857
 
 
858
                        /*
 
859
                         * Initial values of theirstdoffset and theirdstoffset.
 
860
                         */
 
861
                        theirstdoffset = 0;
 
862
                        for (i = 0; i < sp->timecnt; ++i)
 
863
                        {
 
864
                                j = sp->types[i];
 
865
                                if (!sp->ttis[j].tt_isdst)
 
866
                                {
 
867
                                        theirstdoffset =
 
868
                                                -sp->ttis[j].tt_gmtoff;
 
869
                                        break;
 
870
                                }
 
871
                        }
 
872
                        theirdstoffset = 0;
 
873
                        for (i = 0; i < sp->timecnt; ++i)
 
874
                        {
 
875
                                j = sp->types[i];
 
876
                                if (sp->ttis[j].tt_isdst)
 
877
                                {
 
878
                                        theirdstoffset =
 
879
                                                -sp->ttis[j].tt_gmtoff;
 
880
                                        break;
 
881
                                }
 
882
                        }
 
883
 
 
884
                        /*
 
885
                         * Initially we're assumed to be in standard time.
 
886
                         */
 
887
                        isdst = FALSE;
 
888
                        theiroffset = theirstdoffset;
 
889
 
 
890
                        /*
 
891
                         * Now juggle transition times and types tracking offsets as you
 
892
                         * do.
 
893
                         */
 
894
                        for (i = 0; i < sp->timecnt; ++i)
 
895
                        {
 
896
                                j = sp->types[i];
 
897
                                sp->types[i] = sp->ttis[j].tt_isdst;
 
898
                                if (sp->ttis[j].tt_ttisgmt)
 
899
                                {
 
900
                                        /* No adjustment to transition time */
 
901
                                }
 
902
                                else
 
903
                                {
 
904
                                        /*
 
905
                                         * If summer time is in effect, and the transition time
 
906
                                         * was not specified as standard time, add the summer time
 
907
                                         * offset to the transition time; otherwise, add the
 
908
                                         * standard time offset to the transition time.
 
909
                                         */
 
910
 
 
911
                                        /*
 
912
                                         * Transitions from DST to DDST will effectively disappear
 
913
                                         * since POSIX provides for only one DST offset.
 
914
                                         */
 
915
                                        if (isdst && !sp->ttis[j].tt_ttisstd)
 
916
                                        {
 
917
                                                sp->ats[i] += dstoffset -
 
918
                                                        theirdstoffset;
 
919
                                        }
 
920
                                        else
 
921
                                        {
 
922
                                                sp->ats[i] += stdoffset -
 
923
                                                        theirstdoffset;
 
924
                                        }
 
925
                                }
 
926
                                theiroffset = -sp->ttis[j].tt_gmtoff;
 
927
                                if (sp->ttis[j].tt_isdst)
 
928
                                        theirdstoffset = theiroffset;
 
929
                                else
 
930
                                        theirstdoffset = theiroffset;
 
931
                        }
 
932
 
 
933
                        /*
 
934
                         * Finally, fill in ttis. ttisstd and ttisgmt need not be handled.
 
935
                         */
 
936
                        sp->ttis[0].tt_gmtoff = -stdoffset;
 
937
                        sp->ttis[0].tt_isdst = FALSE;
 
938
                        sp->ttis[0].tt_abbrind = 0;
 
939
                        sp->ttis[1].tt_gmtoff = -dstoffset;
 
940
                        sp->ttis[1].tt_isdst = TRUE;
 
941
                        sp->ttis[1].tt_abbrind = stdlen + 1;
 
942
                        sp->typecnt = 2;
 
943
                }
 
944
        }
 
945
        else
 
946
        {
 
947
                dstlen = 0;
 
948
                sp->typecnt = 1;                /* only standard time */
 
949
                sp->timecnt = 0;
 
950
                sp->ttis[0].tt_gmtoff = -stdoffset;
 
951
                sp->ttis[0].tt_isdst = 0;
 
952
                sp->ttis[0].tt_abbrind = 0;
 
953
        }
 
954
        sp->charcnt = stdlen + 1;
 
955
        if (dstlen != 0)
 
956
                sp->charcnt += dstlen + 1;
 
957
        if ((size_t) sp->charcnt > sizeof sp->chars)
 
958
                return -1;
 
959
        cp = sp->chars;
 
960
        (void) strncpy(cp, stdname, stdlen);
 
961
        cp += stdlen;
 
962
        *cp++ = '\0';
 
963
        if (dstlen != 0)
 
964
        {
 
965
                (void) strncpy(cp, dstname, dstlen);
 
966
                *(cp + dstlen) = '\0';
 
967
        }
 
968
        return 0;
 
969
}
 
970
 
 
971
static void
 
972
gmtload(struct state * sp)
 
973
{
 
974
        if (tzload(gmt, NULL, sp, TRUE) != 0)
 
975
                (void) tzparse(gmt, sp, TRUE);
 
976
}
 
977
 
 
978
 
 
979
/*
 
980
 * The easy way to behave "as if no library function calls" localtime
 
981
 * is to not call it--so we drop its guts into "localsub", which can be
 
982
 * freely called. (And no, the PANS doesn't require the above behavior--
 
983
 * but it *is* desirable.)
 
984
 *
 
985
 * The unused offset argument is for the benefit of mktime variants.
 
986
 */
 
987
static struct pg_tm *
 
988
localsub(const pg_time_t *timep, long offset,
 
989
                 struct pg_tm *tmp, const pg_tz *tz)
 
990
{
 
991
        const struct state *sp;
 
992
        const struct ttinfo *ttisp;
 
993
        int                     i;
 
994
        struct pg_tm *result;
 
995
        const pg_time_t t = *timep;
 
996
 
 
997
        sp = &tz->state;
 
998
        if ((sp->goback && t < sp->ats[0]) ||
 
999
                (sp->goahead && t > sp->ats[sp->timecnt - 1]))
 
1000
        {
 
1001
                pg_time_t       newt = t;
 
1002
                pg_time_t       seconds;
 
1003
                pg_time_t       tcycles;
 
1004
                int64           icycles;
 
1005
 
 
1006
                if (t < sp->ats[0])
 
1007
                        seconds = sp->ats[0] - t;
 
1008
                else    seconds = t - sp->ats[sp->timecnt - 1];
 
1009
                --seconds;
 
1010
                tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
 
1011
                ++tcycles;
 
1012
                icycles = tcycles;
 
1013
                if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
 
1014
                        return NULL;
 
1015
                seconds = icycles;
 
1016
                seconds *= YEARSPERREPEAT;
 
1017
                seconds *= AVGSECSPERYEAR;
 
1018
                if (t < sp->ats[0])
 
1019
                        newt += seconds;
 
1020
                else    newt -= seconds;
 
1021
                if (newt < sp->ats[0] ||
 
1022
                        newt > sp->ats[sp->timecnt - 1])
 
1023
                        return NULL;    /* "cannot happen" */
 
1024
                result = localsub(&newt, offset, tmp, tz);
 
1025
                if (result == tmp)
 
1026
                {
 
1027
                        pg_time_t newy;
 
1028
 
 
1029
                        newy = tmp->tm_year;
 
1030
                        if (t < sp->ats[0])
 
1031
                                newy -= icycles * YEARSPERREPEAT;
 
1032
                        else    newy += icycles * YEARSPERREPEAT;
 
1033
                        tmp->tm_year = newy;
 
1034
                        if (tmp->tm_year != newy)
 
1035
                                return NULL;
 
1036
                }
 
1037
                return result;
 
1038
        }
 
1039
        if (sp->timecnt == 0 || t < sp->ats[0])
 
1040
        {
 
1041
                i = 0;
 
1042
                while (sp->ttis[i].tt_isdst)
 
1043
                        if (++i >= sp->typecnt)
 
1044
                        {
 
1045
                                i = 0;
 
1046
                                break;
 
1047
                        }
 
1048
        }
 
1049
        else
 
1050
        {
 
1051
                int    lo = 1;
 
1052
                int    hi = sp->timecnt;
 
1053
 
 
1054
                while (lo < hi)
 
1055
                {
 
1056
                        int    mid = (lo + hi) >> 1;
 
1057
 
 
1058
                        if (t < sp->ats[mid])
 
1059
                                hi = mid;
 
1060
                        else    lo = mid + 1;
 
1061
                }
 
1062
                i = (int) sp->types[lo - 1];
 
1063
        }
 
1064
        ttisp = &sp->ttis[i];
 
1065
 
 
1066
        result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
 
1067
        tmp->tm_isdst = ttisp->tt_isdst;
 
1068
        tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
 
1069
        return result;
 
1070
}
 
1071
 
 
1072
 
 
1073
struct pg_tm *
 
1074
pg_localtime(const pg_time_t *timep, const pg_tz *tz)
 
1075
{
 
1076
        return localsub(timep, 0L, &tm, tz);
 
1077
}
 
1078
 
 
1079
 
 
1080
/*
 
1081
 * gmtsub is to gmtime as localsub is to localtime.
 
1082
 */
 
1083
static struct pg_tm *
 
1084
gmtsub(const pg_time_t *timep, long offset, struct pg_tm *tmp)
 
1085
{
 
1086
        struct pg_tm *result;
 
1087
 
 
1088
        if (!gmt_is_set)
 
1089
        {
 
1090
                gmt_is_set = TRUE;
 
1091
                gmtload(gmtptr);
 
1092
        }
 
1093
        result = timesub(timep, offset, gmtptr, tmp);
 
1094
 
 
1095
        /*
 
1096
         * Could get fancy here and deliver something such as "UTC+xxxx" or
 
1097
         * "UTC-xxxx" if offset is non-zero, but this is no time for a treasure
 
1098
         * hunt.
 
1099
         */
 
1100
        if (offset != 0)
 
1101
                tmp->tm_zone = wildabbr;
 
1102
        else
 
1103
                tmp->tm_zone = gmtptr->chars;
 
1104
 
 
1105
        return result;
 
1106
}
 
1107
 
 
1108
struct pg_tm *
 
1109
pg_gmtime(const pg_time_t *timep)
 
1110
{
 
1111
        return gmtsub(timep, 0L, &tm);
 
1112
}
 
1113
 
 
1114
/*
 
1115
 * Return the number of leap years through the end of the given year
 
1116
 * where, to make the math easy, the answer for year zero is defined as zero.
 
1117
 */
 
1118
static int
 
1119
leaps_thru_end_of(const int y)
 
1120
{
 
1121
        return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
 
1122
                -(leaps_thru_end_of(-(y + 1)) + 1);
 
1123
}
 
1124
 
 
1125
 
 
1126
static struct pg_tm *
 
1127
timesub(const pg_time_t *timep, long offset,
 
1128
                const struct state *sp, struct pg_tm *tmp)
 
1129
{
 
1130
        const struct lsinfo *lp;
 
1131
        pg_time_t       tdays;
 
1132
        int                     idays;  /* unsigned would be so 2003 */
 
1133
        long            rem;
 
1134
        int                     y;
 
1135
        const int  *ip;
 
1136
        long            corr;
 
1137
        int                     hit;
 
1138
        int                     i;
 
1139
 
 
1140
        corr = 0;
 
1141
        hit = 0;
 
1142
        i = sp->leapcnt;
 
1143
        while (--i >= 0)
 
1144
        {
 
1145
                lp = &sp->lsis[i];
 
1146
                if (*timep >= lp->ls_trans)
 
1147
                {
 
1148
                        if (*timep == lp->ls_trans)
 
1149
                        {
 
1150
                                hit = ((i == 0 && lp->ls_corr > 0) ||
 
1151
                                           lp->ls_corr > sp->lsis[i - 1].ls_corr);
 
1152
                                if (hit)
 
1153
                                        while (i > 0 &&
 
1154
                                                   sp->lsis[i].ls_trans ==
 
1155
                                                   sp->lsis[i - 1].ls_trans + 1 &&
 
1156
                                                   sp->lsis[i].ls_corr ==
 
1157
                                                   sp->lsis[i - 1].ls_corr + 1)
 
1158
                                        {
 
1159
                                                ++hit;
 
1160
                                                --i;
 
1161
                                        }
 
1162
                        }
 
1163
                        corr = lp->ls_corr;
 
1164
                        break;
 
1165
                }
 
1166
        }
 
1167
        y = EPOCH_YEAR;
 
1168
        tdays = *timep / SECSPERDAY;
 
1169
        rem = *timep - tdays * SECSPERDAY;
 
1170
        while (tdays < 0 || tdays >= year_lengths[isleap(y)])
 
1171
        {
 
1172
                int             newy;
 
1173
                pg_time_t       tdelta;
 
1174
                int             idelta;
 
1175
                int             leapdays;
 
1176
 
 
1177
                tdelta = tdays / DAYSPERLYEAR;
 
1178
                idelta = tdelta;
 
1179
                if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
 
1180
                        return NULL;
 
1181
                if (idelta == 0)
 
1182
                        idelta = (tdays < 0) ? -1 : 1;
 
1183
                newy = y;
 
1184
                if (increment_overflow(&newy, idelta))
 
1185
                        return NULL;
 
1186
                leapdays = leaps_thru_end_of(newy - 1) -
 
1187
                        leaps_thru_end_of(y - 1);
 
1188
                tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
 
1189
                tdays -= leapdays;
 
1190
                y = newy;
 
1191
        }
 
1192
        {
 
1193
                long   seconds;
 
1194
 
 
1195
                seconds = tdays * SECSPERDAY + 0.5;
 
1196
                tdays = seconds / SECSPERDAY;
 
1197
                rem += seconds - tdays * SECSPERDAY;
 
1198
        }
 
1199
        /*
 
1200
         * Given the range, we can now fearlessly cast...
 
1201
         */
 
1202
        idays = tdays;
 
1203
        rem += offset - corr;
 
1204
        while (rem < 0)
 
1205
        {
 
1206
                rem += SECSPERDAY;
 
1207
                --idays;
 
1208
        }
 
1209
        while (rem >= SECSPERDAY)
 
1210
        {
 
1211
                rem -= SECSPERDAY;
 
1212
                ++idays;
 
1213
        }
 
1214
        while (idays < 0)
 
1215
        {
 
1216
                if (increment_overflow(&y, -1))
 
1217
                        return NULL;
 
1218
                idays += year_lengths[isleap(y)];
 
1219
        }
 
1220
        while (idays >= year_lengths[isleap(y)])
 
1221
        {
 
1222
                idays -= year_lengths[isleap(y)];
 
1223
                if (increment_overflow(&y, 1))
 
1224
                        return NULL;
 
1225
        }
 
1226
        tmp->tm_year = y;
 
1227
        if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
 
1228
                return NULL;
 
1229
        tmp->tm_yday = idays;
 
1230
        /*
 
1231
         * The "extra" mods below avoid overflow problems.
 
1232
         */
 
1233
        tmp->tm_wday = EPOCH_WDAY +
 
1234
                ((y - EPOCH_YEAR) % DAYSPERWEEK) *
 
1235
                (DAYSPERNYEAR % DAYSPERWEEK) +
 
1236
                leaps_thru_end_of(y - 1) -
 
1237
                leaps_thru_end_of(EPOCH_YEAR - 1) +
 
1238
                idays;
 
1239
        tmp->tm_wday %= DAYSPERWEEK;
 
1240
        if (tmp->tm_wday < 0)
 
1241
                tmp->tm_wday += DAYSPERWEEK;
 
1242
        tmp->tm_hour = (int) (rem / SECSPERHOUR);
 
1243
        rem %= SECSPERHOUR;
 
1244
        tmp->tm_min = (int) (rem / SECSPERMIN);
 
1245
 
 
1246
        /*
 
1247
         * A positive leap second requires a special representation. This uses
 
1248
         * "... ??:59:60" et seq.
 
1249
         */
 
1250
        tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
 
1251
        ip = mon_lengths[isleap(y)];
 
1252
        for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
 
1253
                idays -= ip[tmp->tm_mon];
 
1254
        tmp->tm_mday = (int) (idays + 1);
 
1255
        tmp->tm_isdst = 0;
 
1256
        tmp->tm_gmtoff = offset;
 
1257
        return tmp;
 
1258
}
 
1259
 
 
1260
/*
 
1261
 * Simplified normalize logic courtesy Paul Eggert.
 
1262
 */
 
1263
 
 
1264
static int
 
1265
increment_overflow(int *number, int delta)
 
1266
{
 
1267
        int     number0;
 
1268
 
 
1269
        number0 = *number;
 
1270
        *number += delta;
 
1271
        return (*number < number0) != (delta < 0);
 
1272
}
 
1273
 
 
1274
/*
 
1275
 * Find the next DST transition time at or after the given time
 
1276
 *
 
1277
 * *timep is the input value, the other parameters are output values.
 
1278
 *
 
1279
 * When the function result is 1, *boundary is set to the time_t
 
1280
 * representation of the next DST transition time at or after *timep,
 
1281
 * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
 
1282
 * state prevailing just before that boundary, and *after_gmtoff and
 
1283
 * *after_isdst are set to the state prevailing just after that boundary.
 
1284
 *
 
1285
 * When the function result is 0, there is no known DST transition at or
 
1286
 * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
 
1287
 * offset and isdst state prevailing at *timep.  (This would occur in
 
1288
 * DST-less time zones, for example.)
 
1289
 *
 
1290
 * A function result of -1 indicates failure (this case does not actually
 
1291
 * occur in our current implementation).
 
1292
 */
 
1293
int
 
1294
pg_next_dst_boundary(const pg_time_t *timep,
 
1295
                                         long int *before_gmtoff,
 
1296
                                         int *before_isdst,
 
1297
                                         pg_time_t *boundary,
 
1298
                                         long int *after_gmtoff,
 
1299
                                         int *after_isdst,
 
1300
                                         const pg_tz *tz)
 
1301
{
 
1302
        const struct state *sp;
 
1303
        const struct ttinfo *ttisp;
 
1304
        int                     i;
 
1305
        int                     j;
 
1306
        const pg_time_t t = *timep;
 
1307
 
 
1308
        sp = &tz->state;
 
1309
        if (sp->timecnt == 0)
 
1310
        {
 
1311
                /* non-DST zone, use lowest-numbered standard type */
 
1312
                i = 0;
 
1313
                while (sp->ttis[i].tt_isdst)
 
1314
                        if (++i >= sp->typecnt)
 
1315
                        {
 
1316
                                i = 0;
 
1317
                                break;
 
1318
                        }
 
1319
                ttisp = &sp->ttis[i];
 
1320
                *before_gmtoff = ttisp->tt_gmtoff;
 
1321
                *before_isdst = ttisp->tt_isdst;
 
1322
                return 0;
 
1323
        }
 
1324
        if ((sp->goback && t < sp->ats[0]) ||
 
1325
                (sp->goahead && t > sp->ats[sp->timecnt - 1]))
 
1326
        {
 
1327
                /* For values outside the transition table, extrapolate */
 
1328
                pg_time_t       newt = t;
 
1329
                pg_time_t       seconds;
 
1330
                pg_time_t       tcycles;
 
1331
                int64           icycles;
 
1332
                int                     result;
 
1333
                
 
1334
                if (t < sp->ats[0])
 
1335
                        seconds = sp->ats[0] - t;
 
1336
                else    seconds = t - sp->ats[sp->timecnt - 1];
 
1337
                --seconds;
 
1338
                tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
 
1339
                ++tcycles;
 
1340
                icycles = tcycles;
 
1341
                if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
 
1342
                        return -1;
 
1343
                seconds = icycles;
 
1344
                seconds *= YEARSPERREPEAT;
 
1345
                seconds *= AVGSECSPERYEAR;
 
1346
                if (t < sp->ats[0])
 
1347
                        newt += seconds;
 
1348
                else    newt -= seconds;
 
1349
                if (newt < sp->ats[0] ||
 
1350
                        newt > sp->ats[sp->timecnt - 1])
 
1351
                        return -1;    /* "cannot happen" */
 
1352
 
 
1353
                result = pg_next_dst_boundary(&newt, before_gmtoff,
 
1354
                                                                          before_isdst,
 
1355
                                                                          boundary,
 
1356
                                                                          after_gmtoff,
 
1357
                                                                          after_isdst,
 
1358
                                                                          tz);
 
1359
                if (t < sp->ats[0])
 
1360
                        *boundary -= seconds;
 
1361
                else
 
1362
                        *boundary += seconds;
 
1363
                return result;
 
1364
        }
 
1365
 
 
1366
        if (t > sp->ats[sp->timecnt - 1])
 
1367
        {
 
1368
                /* No known transition >= t, so use last known segment's type */
 
1369
                i = sp->types[sp->timecnt - 1];
 
1370
                ttisp = &sp->ttis[i];
 
1371
                *before_gmtoff = ttisp->tt_gmtoff;
 
1372
                *before_isdst = ttisp->tt_isdst;
 
1373
                return 0;
 
1374
        }
 
1375
        if (t <= sp->ats[0])
 
1376
        {
 
1377
                /* For "before", use lowest-numbered standard type */
 
1378
                i = 0;
 
1379
                while (sp->ttis[i].tt_isdst)
 
1380
                        if (++i >= sp->typecnt)
 
1381
                        {
 
1382
                                i = 0;
 
1383
                                break;
 
1384
                        }
 
1385
                ttisp = &sp->ttis[i];
 
1386
                *before_gmtoff = ttisp->tt_gmtoff;
 
1387
                *before_isdst = ttisp->tt_isdst;
 
1388
                *boundary = sp->ats[0];
 
1389
                /* And for "after", use the first segment's type */
 
1390
                i = sp->types[0];
 
1391
                ttisp = &sp->ttis[i];
 
1392
                *after_gmtoff = ttisp->tt_gmtoff;
 
1393
                *after_isdst = ttisp->tt_isdst;
 
1394
                return 1;
 
1395
        }
 
1396
        /* Else search to find the containing segment */
 
1397
        {
 
1398
                int    lo = 1;
 
1399
                int    hi = sp->timecnt;
 
1400
 
 
1401
                while (lo < hi)
 
1402
                {
 
1403
                        int    mid = (lo + hi) >> 1;
 
1404
 
 
1405
                        if (t < sp->ats[mid])
 
1406
                                hi = mid;
 
1407
                        else    lo = mid + 1;
 
1408
                }
 
1409
                i = lo;
 
1410
        }
 
1411
        j = sp->types[i - 1];
 
1412
        ttisp = &sp->ttis[j];
 
1413
        *before_gmtoff = ttisp->tt_gmtoff;
 
1414
        *before_isdst = ttisp->tt_isdst;
 
1415
        *boundary = sp->ats[i];
 
1416
        j = sp->types[i];
 
1417
        ttisp = &sp->ttis[j];
 
1418
        *after_gmtoff = ttisp->tt_gmtoff;
 
1419
        *after_isdst = ttisp->tt_isdst;
 
1420
        return 1;
 
1421
}
 
1422
 
 
1423
/*
 
1424
 * If the given timezone uses only one GMT offset, store that offset
 
1425
 * into *gmtoff and return TRUE, else return FALSE.
 
1426
 */
 
1427
bool
 
1428
pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
 
1429
{
 
1430
        /*
 
1431
         * The zone could have more than one ttinfo, if it's historically used
 
1432
         * more than one abbreviation.  We return TRUE as long as they all have
 
1433
         * the same gmtoff.
 
1434
         */
 
1435
        const struct state *sp;
 
1436
        int                     i;
 
1437
 
 
1438
        sp = &tz->state;
 
1439
        for (i = 1; i < sp->typecnt; i++)
 
1440
        {
 
1441
                if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
 
1442
                        return false;
 
1443
        }
 
1444
        *gmtoff = sp->ttis[0].tt_gmtoff;
 
1445
        return true;
 
1446
}
 
1447
 
 
1448
/*
 
1449
 * Return the name of the current timezone
 
1450
 */
 
1451
const char *
 
1452
pg_get_timezone_name(pg_tz *tz)
 
1453
{
 
1454
        if (tz)
 
1455
                return tz->TZname;
 
1456
        return NULL;
 
1457
}