2 * This file is in the public domain, so clarified as of
3 * 1996-06-05 by Arthur David Olson.
10 * Leap second handling from Bradley White.
11 * POSIX-style TZ environment variable handling from Guy Harris.
14 /* this file needs to build in both frontend and backend contexts */
26 * Someone might make incorrect use of a time zone abbreviation:
27 * 1. They might reference tzname[0] before calling tzset (explicitly
29 * 2. They might reference tzname[1] before calling tzset (explicitly
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).
46 #endif /* !defined WILDABBR */
48 static char wildabbr
[] = WILDABBR
;
50 static const char gmt
[] = "GMT";
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
59 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
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 */
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 */
75 * Prototypes for static functions.
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
,
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
);
100 static struct state gmtmem
;
102 #define gmtptr (&gmtmem)
105 static int gmt_is_set
= 0;
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.
115 static struct pg_tm tm
;
119 detzcode(const char *codep
)
124 result
= (codep
[0] & 0x80) ? ~0L : 0;
125 for (i
= 0; i
< 4; ++i
)
126 result
= (result
<< 8) | (codep
[i
] & 0xff);
131 detzcode64(const char *codep
)
136 result
= (codep
[0] & 0x80) ? (~(int64
) 0) : 0;
137 for (i
= 0; i
< 8; ++i
)
138 result
= result
* 256 + (codep
[i
] & 0xff);
143 differ_by_repeat(pg_time_t t1
, pg_time_t t0
)
145 if (TYPE_INTEGRAL(pg_time_t
) &&
146 TYPE_BIT(pg_time_t
) - TYPE_SIGNED(pg_time_t
) < SECSPERREPEAT_BITS
)
148 return t1
- t0
== SECSPERREPEAT
;
152 tzload(const char *name
, char *canonname
, struct state
* sp
, int doextend
)
161 struct tzhead tzhead
;
162 char buf
[2 * sizeof(struct tzhead
) +
167 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
171 fid
= pg_open_tzfile(name
, canonname
);
174 nread
= read(fid
, u
.buf
, sizeof u
.buf
);
175 if (close(fid
) != 0 || nread
<= 0)
177 for (stored
= 4; stored
<= 8; stored
*= 2)
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))
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 */
205 for (i
= 0; i
< sp
->timecnt
; ++i
)
207 sp
->ats
[i
] = (stored
== 4) ? detzcode(p
) : detzcode64(p
);
210 for (i
= 0; i
< sp
->timecnt
; ++i
)
212 sp
->types
[i
] = (unsigned char) *p
++;
213 if (sp
->types
[i
] >= sp
->typecnt
)
216 for (i
= 0; i
< sp
->typecnt
; ++i
)
218 struct ttinfo
*ttisp
;
220 ttisp
= &sp
->ttis
[i
];
221 ttisp
->tt_gmtoff
= detzcode(p
);
223 ttisp
->tt_isdst
= (unsigned char) *p
++;
224 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
226 ttisp
->tt_abbrind
= (unsigned char) *p
++;
227 if (ttisp
->tt_abbrind
< 0 ||
228 ttisp
->tt_abbrind
> sp
->charcnt
)
231 for (i
= 0; i
< sp
->charcnt
; ++i
)
233 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
234 for (i
= 0; i
< sp
->leapcnt
; ++i
)
236 struct lsinfo
*lsisp
;
238 lsisp
= &sp
->lsis
[i
];
239 lsisp
->ls_trans
= (stored
== 4) ? detzcode(p
) : detzcode64(p
);
241 lsisp
->ls_corr
= detzcode(p
);
244 for (i
= 0; i
< sp
->typecnt
; ++i
)
246 struct ttinfo
*ttisp
;
248 ttisp
= &sp
->ttis
[i
];
250 ttisp
->tt_ttisstd
= FALSE
;
253 ttisp
->tt_ttisstd
= *p
++;
254 if (ttisp
->tt_ttisstd
!= TRUE
&&
255 ttisp
->tt_ttisstd
!= FALSE
)
259 for (i
= 0; i
< sp
->typecnt
; ++i
)
261 struct ttinfo
*ttisp
;
263 ttisp
= &sp
->ttis
[i
];
265 ttisp
->tt_ttisgmt
= FALSE
;
268 ttisp
->tt_ttisgmt
= *p
++;
269 if (ttisp
->tt_ttisgmt
!= TRUE
&&
270 ttisp
->tt_ttisgmt
!= FALSE
)
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).
279 for (i
= 0; i
< sp
->timecnt
- 2; ++i
)
280 if (sp
->ats
[i
] > sp
->ats
[i
+ 1])
283 if (TYPE_SIGNED(pg_time_t
))
286 * Ignore the end (easy).
293 * Ignore the beginning (harder).
297 for (j
= 0; j
+ i
< sp
->timecnt
; ++j
)
299 sp
->ats
[j
] = sp
->ats
[j
+ i
];
300 sp
->types
[j
] = sp
->types
[j
+ i
];
307 * If this is an old file, we're done.
309 if (u
.tzhead
.tzh_version
[0] == '\0')
312 for (i
= 0; i
< nread
; ++i
)
315 * If this is a narrow integer time_t system, we're done.
317 if (stored
>= (int) sizeof(pg_time_t
) && TYPE_INTEGRAL(pg_time_t
))
320 if (doextend
&& nread
> 2 &&
321 u
.buf
[0] == '\n' && u
.buf
[nread
- 1] == '\n' &&
322 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
)
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
)
332 for (i
= 0; i
< 2; ++i
)
333 ts
.ttis
[i
].tt_abbrind
+=
335 for (i
= 0; i
< ts
.charcnt
; ++i
)
336 sp
->chars
[sp
->charcnt
++] =
339 while (i
< ts
.timecnt
&&
341 sp
->ats
[sp
->timecnt
- 1])
343 while (i
< ts
.timecnt
&&
344 sp
->timecnt
< TZ_MAX_TIMES
)
346 sp
->ats
[sp
->timecnt
] =
348 sp
->types
[sp
->timecnt
] =
354 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
355 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
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
]);
372 typesequiv(const struct state
*sp
, int a
, int b
)
377 a
< 0 || a
>= sp
->typecnt
||
378 b
< 0 || b
>= sp
->typecnt
)
382 const struct ttinfo
*ap
= &sp
->ttis
[a
];
383 const struct ttinfo
*bp
= &sp
->ttis
[b
];
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;
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}
400 static const int year_lengths
[2] = {
401 DAYSPERNYEAR
, DAYSPERLYEAR
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
410 getzname(const char *strp
)
414 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
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.
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.
429 getqzname(const char *strp
, int delim
)
433 while ((c
= *strp
) != '\0' && c
!= delim
)
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
442 * Otherwise, return a pointer to the first character not part of the number.
445 getnum(const char *strp
, int *nump
, int min
, int max
)
450 if (strp
== NULL
|| !is_digit(c
= *strp
))
455 num
= num
* 10 + (c
- '0');
457 return NULL
; /* illegal value */
459 } while (is_digit(c
));
461 return NULL
; /* illegal value */
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
474 getsecs(const char *strp
, long *secsp
)
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''.
483 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
486 *secsp
= num
* (long) SECSPERHOUR
;
490 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
493 *secsp
+= num
* SECSPERMIN
;
497 /* `SECSPERMIN' allows for leap seconds. */
498 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
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.
514 getoffset(const char *strp
, long *offsetp
)
523 else if (*strp
== '+')
525 strp
= getsecs(strp
, offsetp
);
527 return NULL
; /* illegal time */
529 *offsetp
= -*offsetp
;
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.
540 getrule(const char *strp
, struct rule
* rulep
)
547 rulep
->r_type
= JULIAN_DAY
;
549 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
551 else if (*strp
== 'M')
556 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
558 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
563 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
568 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
570 else if (is_digit(*strp
))
575 rulep
->r_type
= DAY_OF_YEAR
;
576 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
579 return NULL
; /* invalid format */
588 strp
= getsecs(strp
, &rulep
->r_time
);
591 rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
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.
601 transtime(pg_time_t janfirst
, int year
,
602 const struct rule
* rulep
, long offset
)
614 leapyear
= isleap(year
);
615 switch (rulep
->r_type
)
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.
626 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
627 if (leapyear
&& rulep
->r_day
>= 60)
634 * n - day of year. Just add SECSPERDAY times the day number to
635 * the time of January 1, midnight, to get the day.
637 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
640 case MONTH_NTH_DAY_OF_WEEK
:
643 * Mm.n.d - nth "dth day" of month m.
646 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
647 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
650 * Use Zeller's Congruence to get day-of-week of first day of
653 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
654 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
657 dow
= ((26 * m1
- 2) / 10 +
658 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
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.
666 d
= rulep
->r_day
- dow
;
669 for (i
= 1; i
< rulep
->r_week
; ++i
)
671 if (d
+ DAYSPERWEEK
>=
672 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
678 * "d" is the day-of-month (zero-origin) of the day we want.
680 value
+= d
* SECSPERDAY
;
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.
689 return value
+ rulep
->r_time
+ offset
;
693 * Given a POSIX section 8-style TZ string, fill in the rule tables as
698 tzparse(const char *name
, struct state
* sp
, int lastditch
)
701 const char *dstname
= NULL
;
707 unsigned char *typep
;
714 stdlen
= strlen(name
); /* length of standard zone name */
716 if (stdlen
>= sizeof sp
->chars
)
717 stdlen
= (sizeof sp
->chars
) - 1;
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.
733 name
= getqzname(name
, '>');
736 stdlen
= name
- stdname
;
741 name
= getzname(name
);
742 stdlen
= name
- stdname
;
746 name
= getoffset(name
, &stdoffset
);
749 load_result
= tzload(TZDEFRULES
, NULL
, sp
, FALSE
);
751 if (load_result
!= 0)
752 sp
->leapcnt
= 0; /* so, we're off a little */
758 name
= getqzname(name
, '>');
761 dstlen
= name
- dstname
;
767 name
= getzname(name
);
768 dstlen
= name
- dstname
; /* length of DST zone name */
770 if (*name
!= '\0' && *name
!= ',' && *name
!= ';')
772 name
= getoffset(name
, &dstoffset
);
777 dstoffset
= stdoffset
- SECSPERHOUR
;
778 if (*name
== '\0' && load_result
!= 0)
779 name
= TZDEFRULESTRING
;
780 if (*name
== ',' || *name
== ';')
790 if ((name
= getrule(name
, &start
)) == NULL
)
794 if ((name
= getrule(name
, &end
)) == NULL
)
798 sp
->typecnt
= 2; /* standard time and DST */
801 * Two transitions per year, from EPOCH_YEAR forward.
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;
813 for (year
= EPOCH_YEAR
;
814 sp
->timecnt
+ 2 <= TZ_MAX_TIMES
;
819 starttime
= transtime(janfirst
, year
, &start
,
821 endtime
= transtime(janfirst
, year
, &end
,
823 if (starttime
> endtime
)
826 *typep
++ = 1; /* DST ends */
828 *typep
++ = 0; /* DST begins */
833 *typep
++ = 0; /* DST begins */
835 *typep
++ = 1; /* DST ends */
839 newfirst
+= year_lengths
[isleap(year
)] *
841 if (newfirst
<= janfirst
)
859 * Initial values of theirstdoffset and theirdstoffset.
862 for (i
= 0; i
< sp
->timecnt
; ++i
)
865 if (!sp
->ttis
[j
].tt_isdst
)
868 -sp
->ttis
[j
].tt_gmtoff
;
873 for (i
= 0; i
< sp
->timecnt
; ++i
)
876 if (sp
->ttis
[j
].tt_isdst
)
879 -sp
->ttis
[j
].tt_gmtoff
;
885 * Initially we're assumed to be in standard time.
888 theiroffset
= theirstdoffset
;
891 * Now juggle transition times and types tracking offsets as you
894 for (i
= 0; i
< sp
->timecnt
; ++i
)
897 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
898 if (sp
->ttis
[j
].tt_ttisgmt
)
900 /* No adjustment to transition time */
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.
912 * Transitions from DST to DDST will effectively disappear
913 * since POSIX provides for only one DST offset.
915 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
)
917 sp
->ats
[i
] += dstoffset
-
922 sp
->ats
[i
] += stdoffset
-
926 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
927 if (sp
->ttis
[j
].tt_isdst
)
928 theirdstoffset
= theiroffset
;
930 theirstdoffset
= theiroffset
;
934 * Finally, fill in ttis. ttisstd and ttisgmt need not be handled.
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;
948 sp
->typecnt
= 1; /* only standard time */
950 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
951 sp
->ttis
[0].tt_isdst
= 0;
952 sp
->ttis
[0].tt_abbrind
= 0;
954 sp
->charcnt
= stdlen
+ 1;
956 sp
->charcnt
+= dstlen
+ 1;
957 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
960 (void) strncpy(cp
, stdname
, stdlen
);
965 (void) strncpy(cp
, dstname
, dstlen
);
966 *(cp
+ dstlen
) = '\0';
972 gmtload(struct state
* sp
)
974 if (tzload(gmt
, NULL
, sp
, TRUE
) != 0)
975 (void) tzparse(gmt
, sp
, TRUE
);
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.)
985 * The unused offset argument is for the benefit of mktime variants.
987 static struct pg_tm
*
988 localsub(const pg_time_t
*timep
, long offset
,
989 struct pg_tm
*tmp
, const pg_tz
*tz
)
991 const struct state
*sp
;
992 const struct ttinfo
*ttisp
;
994 struct pg_tm
*result
;
995 const pg_time_t t
= *timep
;
998 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
999 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1]))
1007 seconds
= sp
->ats
[0] - t
;
1008 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1010 tcycles
= seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
;
1013 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
1016 seconds
*= YEARSPERREPEAT
;
1017 seconds
*= AVGSECSPERYEAR
;
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
);
1029 newy
= tmp
->tm_year
;
1031 newy
-= icycles
* YEARSPERREPEAT
;
1032 else newy
+= icycles
* YEARSPERREPEAT
;
1033 tmp
->tm_year
= newy
;
1034 if (tmp
->tm_year
!= newy
)
1039 if (sp
->timecnt
== 0 || t
< sp
->ats
[0])
1042 while (sp
->ttis
[i
].tt_isdst
)
1043 if (++i
>= sp
->typecnt
)
1052 int hi
= sp
->timecnt
;
1056 int mid
= (lo
+ hi
) >> 1;
1058 if (t
< sp
->ats
[mid
])
1062 i
= (int) sp
->types
[lo
- 1];
1064 ttisp
= &sp
->ttis
[i
];
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
];
1074 pg_localtime(const pg_time_t
*timep
, const pg_tz
*tz
)
1076 return localsub(timep
, 0L, &tm
, tz
);
1081 * gmtsub is to gmtime as localsub is to localtime.
1083 static struct pg_tm
*
1084 gmtsub(const pg_time_t
*timep
, long offset
, struct pg_tm
*tmp
)
1086 struct pg_tm
*result
;
1093 result
= timesub(timep
, offset
, gmtptr
, tmp
);
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
1101 tmp
->tm_zone
= wildabbr
;
1103 tmp
->tm_zone
= gmtptr
->chars
;
1109 pg_gmtime(const pg_time_t
*timep
)
1111 return gmtsub(timep
, 0L, &tm
);
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.
1119 leaps_thru_end_of(const int y
)
1121 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1122 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1126 static struct pg_tm
*
1127 timesub(const pg_time_t
*timep
, long offset
,
1128 const struct state
*sp
, struct pg_tm
*tmp
)
1130 const struct lsinfo
*lp
;
1132 int idays
; /* unsigned would be so 2003 */
1146 if (*timep
>= lp
->ls_trans
)
1148 if (*timep
== lp
->ls_trans
)
1150 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1151 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
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)
1168 tdays
= *timep
/ SECSPERDAY
;
1169 rem
= *timep
- tdays
* SECSPERDAY
;
1170 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)])
1177 tdelta
= tdays
/ DAYSPERLYEAR
;
1179 if (tdelta
- idelta
>= 1 || idelta
- tdelta
>= 1)
1182 idelta
= (tdays
< 0) ? -1 : 1;
1184 if (increment_overflow(&newy
, idelta
))
1186 leapdays
= leaps_thru_end_of(newy
- 1) -
1187 leaps_thru_end_of(y
- 1);
1188 tdays
-= ((pg_time_t
) newy
- y
) * DAYSPERNYEAR
;
1195 seconds
= tdays
* SECSPERDAY
+ 0.5;
1196 tdays
= seconds
/ SECSPERDAY
;
1197 rem
+= seconds
- tdays
* SECSPERDAY
;
1200 * Given the range, we can now fearlessly cast...
1203 rem
+= offset
- corr
;
1209 while (rem
>= SECSPERDAY
)
1216 if (increment_overflow(&y
, -1))
1218 idays
+= year_lengths
[isleap(y
)];
1220 while (idays
>= year_lengths
[isleap(y
)])
1222 idays
-= year_lengths
[isleap(y
)];
1223 if (increment_overflow(&y
, 1))
1227 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1229 tmp
->tm_yday
= idays
;
1231 * The "extra" mods below avoid overflow problems.
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) +
1239 tmp
->tm_wday
%= DAYSPERWEEK
;
1240 if (tmp
->tm_wday
< 0)
1241 tmp
->tm_wday
+= DAYSPERWEEK
;
1242 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1244 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1247 * A positive leap second requires a special representation. This uses
1248 * "... ??:59:60" et seq.
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);
1256 tmp
->tm_gmtoff
= offset
;
1261 * Simplified normalize logic courtesy Paul Eggert.
1265 increment_overflow(int *number
, int delta
)
1271 return (*number
< number0
) != (delta
< 0);
1275 * Find the next DST transition time at or after the given time
1277 * *timep is the input value, the other parameters are output values.
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.
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.)
1290 * A function result of -1 indicates failure (this case does not actually
1291 * occur in our current implementation).
1294 pg_next_dst_boundary(const pg_time_t
*timep
,
1295 long int *before_gmtoff
,
1297 pg_time_t
*boundary
,
1298 long int *after_gmtoff
,
1302 const struct state
*sp
;
1303 const struct ttinfo
*ttisp
;
1306 const pg_time_t t
= *timep
;
1309 if (sp
->timecnt
== 0)
1311 /* non-DST zone, use lowest-numbered standard type */
1313 while (sp
->ttis
[i
].tt_isdst
)
1314 if (++i
>= sp
->typecnt
)
1319 ttisp
= &sp
->ttis
[i
];
1320 *before_gmtoff
= ttisp
->tt_gmtoff
;
1321 *before_isdst
= ttisp
->tt_isdst
;
1324 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1325 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1]))
1327 /* For values outside the transition table, extrapolate */
1335 seconds
= sp
->ats
[0] - t
;
1336 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1338 tcycles
= seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
;
1341 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
1344 seconds
*= YEARSPERREPEAT
;
1345 seconds
*= AVGSECSPERYEAR
;
1348 else newt
-= seconds
;
1349 if (newt
< sp
->ats
[0] ||
1350 newt
> sp
->ats
[sp
->timecnt
- 1])
1351 return -1; /* "cannot happen" */
1353 result
= pg_next_dst_boundary(&newt
, before_gmtoff
,
1360 *boundary
-= seconds
;
1362 *boundary
+= seconds
;
1366 if (t
> sp
->ats
[sp
->timecnt
- 1])
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
;
1375 if (t
<= sp
->ats
[0])
1377 /* For "before", use lowest-numbered standard type */
1379 while (sp
->ttis
[i
].tt_isdst
)
1380 if (++i
>= sp
->typecnt
)
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 */
1391 ttisp
= &sp
->ttis
[i
];
1392 *after_gmtoff
= ttisp
->tt_gmtoff
;
1393 *after_isdst
= ttisp
->tt_isdst
;
1396 /* Else search to find the containing segment */
1399 int hi
= sp
->timecnt
;
1403 int mid
= (lo
+ hi
) >> 1;
1405 if (t
< sp
->ats
[mid
])
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
];
1417 ttisp
= &sp
->ttis
[j
];
1418 *after_gmtoff
= ttisp
->tt_gmtoff
;
1419 *after_isdst
= ttisp
->tt_isdst
;
1424 * If the given timezone uses only one GMT offset, store that offset
1425 * into *gmtoff and return TRUE, else return FALSE.
1428 pg_get_timezone_offset(const pg_tz
*tz
, long int *gmtoff
)
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
1435 const struct state
*sp
;
1439 for (i
= 1; i
< sp
->typecnt
; i
++)
1441 if (sp
->ttis
[i
].tt_gmtoff
!= sp
->ttis
[0].tt_gmtoff
)
1444 *gmtoff
= sp
->ttis
[0].tt_gmtoff
;
1449 * Return the name of the current timezone
1452 pg_get_timezone_name(pg_tz
*tz
)