]>
git.saurik.com Git - apple/icu.git/blob - icuSources/tools/tzcode/localtime.c
7a7ebd1ef609f6e02dcf5ffed4f7380343e4bc1f
2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
7 ** Leap second handling from Bradley White.
8 ** POSIX-style TZ environment variable handling from Guy Harris.
17 #ifndef TZ_ABBR_MAX_LEN
18 #define TZ_ABBR_MAX_LEN 16
19 #endif /* !defined TZ_ABBR_MAX_LEN */
21 #ifndef TZ_ABBR_CHAR_SET
22 #define TZ_ABBR_CHAR_SET \
23 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
24 #endif /* !defined TZ_ABBR_CHAR_SET */
26 #ifndef TZ_ABBR_ERR_CHAR
27 #define TZ_ABBR_ERR_CHAR '_'
28 #endif /* !defined TZ_ABBR_ERR_CHAR */
31 ** SunOS 4.1.1 headers lack O_BINARY.
35 #define OPEN_MODE (O_RDONLY | O_BINARY)
36 #endif /* defined O_BINARY */
38 #define OPEN_MODE O_RDONLY
39 #endif /* !defined O_BINARY */
43 ** Someone might make incorrect use of a time zone abbreviation:
44 ** 1. They might reference tzname[0] before calling tzset (explicitly
46 ** 2. They might reference tzname[1] before calling tzset (explicitly
48 ** 3. They might reference tzname[1] after setting to a time zone
49 ** in which Daylight Saving Time is never observed.
50 ** 4. They might reference tzname[0] after setting to a time zone
51 ** in which Standard Time is never observed.
52 ** 5. They might reference tm.TM_ZONE after calling offtime.
53 ** What's best to do in the above cases is open to debate;
54 ** for now, we just set things up so that in any of the five cases
55 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
56 ** string "tzname[0] used before set", and similarly for the other cases.
57 ** And another: initialize tzname[0] to "ERA", with an explanation in the
58 ** manual page of what this "time zone abbreviation" means (doing this so
59 ** that tzname[0] has the "normal" length of three characters).
62 #endif /* !defined WILDABBR */
64 static const char wildabbr
[] = WILDABBR
;
66 static const char gmt
[] = "GMT";
69 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
70 ** We default to US rules as of 1999-08-17.
71 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
72 ** implementation dependent; for historical reasons, US rules are a
75 #ifndef TZDEFRULESTRING
76 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
77 #endif /* !defined TZDEFDST */
79 struct ttinfo
{ /* time type information */
80 int_fast32_t tt_gmtoff
; /* UT offset in seconds */
81 int tt_isdst
; /* used to set tm_isdst */
82 int tt_abbrind
; /* abbreviation list index */
83 int tt_ttisstd
; /* TRUE if transition is std time */
84 int tt_ttisgmt
; /* TRUE if transition is UT */
87 struct lsinfo
{ /* leap second information */
88 time_t ls_trans
; /* transition time */
89 int_fast64_t ls_corr
; /* correction to apply */
92 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
95 #define MY_TZNAME_MAX TZNAME_MAX
96 #endif /* defined TZNAME_MAX */
98 #define MY_TZNAME_MAX 255
99 #endif /* !defined TZNAME_MAX */
108 time_t ats
[TZ_MAX_TIMES
];
109 unsigned char types
[TZ_MAX_TIMES
];
110 struct ttinfo ttis
[TZ_MAX_TYPES
];
111 char chars
[BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
112 (2 * (MY_TZNAME_MAX
+ 1)))];
113 struct lsinfo lsis
[TZ_MAX_LEAPS
];
114 int defaulttype
; /* for early times or if no transitions */
118 int r_type
; /* type of rule--see below */
119 int r_day
; /* day number of rule */
120 int r_week
; /* week number of rule */
121 int r_mon
; /* month number of rule */
122 int_fast32_t r_time
; /* transition time of rule */
125 #define JULIAN_DAY 0 /* Jn - Julian day */
126 #define DAY_OF_YEAR 1 /* n - day of year */
127 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
130 ** Prototypes for static functions.
133 static int_fast32_t detzcode(const char * codep
);
134 static int_fast64_t detzcode64(const char * codep
);
135 static int differ_by_repeat(time_t t1
, time_t t0
);
136 static const char * getzname(const char * strp
) ATTRIBUTE_PURE
;
137 static const char * getqzname(const char * strp
, const int delim
)
139 static const char * getnum(const char * strp
, int * nump
, int min
,
141 static const char * getsecs(const char * strp
, int_fast32_t * secsp
);
142 static const char * getoffset(const char * strp
, int_fast32_t * offsetp
);
143 static const char * getrule(const char * strp
, struct rule
* rulep
);
144 static void gmtload(struct state
* sp
);
145 static struct tm
* gmtsub(const time_t * timep
, int_fast32_t offset
,
147 static struct tm
* localsub(const time_t * timep
, int_fast32_t offset
,
149 static int increment_overflow(int * number
, int delta
);
150 static int leaps_thru_end_of(int y
) ATTRIBUTE_PURE
;
151 static int increment_overflow32(int_fast32_t * number
, int delta
);
152 static int increment_overflow_time(time_t *t
, int_fast32_t delta
);
153 static int normalize_overflow32(int_fast32_t * tensptr
,
154 int * unitsptr
, int base
);
155 static int normalize_overflow(int * tensptr
, int * unitsptr
,
157 static void settzname(void);
158 static time_t time1(struct tm
* tmp
,
159 struct tm
* (*funcp
)(const time_t *,
160 int_fast32_t, struct tm
*),
161 int_fast32_t offset
);
162 static time_t time2(struct tm
*tmp
,
163 struct tm
* (*funcp
)(const time_t *,
164 int_fast32_t, struct tm
*),
165 int_fast32_t offset
, int * okayp
);
166 static time_t time2sub(struct tm
*tmp
,
167 struct tm
* (*funcp
)(const time_t *,
168 int_fast32_t, struct tm
*),
169 int_fast32_t offset
, int * okayp
, int do_norm_secs
);
170 static struct tm
* timesub(const time_t * timep
, int_fast32_t offset
,
171 const struct state
* sp
, struct tm
* tmp
);
172 static int tmcomp(const struct tm
* atmp
,
173 const struct tm
* btmp
);
174 static int_fast32_t transtime(int year
, const struct rule
* rulep
,
177 static int typesequiv(const struct state
* sp
, int a
, int b
);
178 static int tzload(const char * name
, struct state
* sp
,
180 static int tzparse(const char * name
, struct state
* sp
,
184 static struct state
* lclptr
;
185 static struct state
* gmtptr
;
186 #endif /* defined ALL_STATE */
189 static struct state lclmem
;
190 static struct state gmtmem
;
191 #define lclptr (&lclmem)
192 #define gmtptr (&gmtmem)
193 #endif /* State Farm */
195 #ifndef TZ_STRLEN_MAX
196 #define TZ_STRLEN_MAX 255
197 #endif /* !defined TZ_STRLEN_MAX */
199 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
200 static int lcl_is_set
;
201 static int gmt_is_set
;
209 ** Section 4.12.3 of X3.159-1989 requires that
210 ** Except for the strftime function, these functions [asctime,
211 ** ctime, gmtime, localtime] return values in one of two static
212 ** objects: a broken-down time structure and an array of char.
213 ** Thanks to Paul Eggert for noting this.
221 #endif /* defined USG_COMPAT */
225 #endif /* defined ALTZONE */
228 detzcode(const char *const codep
)
230 register int_fast32_t result
;
233 result
= (codep
[0] & 0x80) ? -1 : 0;
234 for (i
= 0; i
< 4; ++i
)
235 result
= (result
<< 8) | (codep
[i
] & 0xff);
240 detzcode64(const char *const codep
)
242 register int_fast64_t result
;
245 result
= (codep
[0] & 0x80) ? -1 : 0;
246 for (i
= 0; i
< 8; ++i
)
247 result
= (result
<< 8) | (codep
[i
] & 0xff);
254 register struct state
* const sp
= lclptr
;
257 tzname
[0] = tzname
[1] = (char *) wildabbr
;
261 #endif /* defined USG_COMPAT */
264 #endif /* defined ALTZONE */
266 tzname
[0] = tzname
[1] = (char *) gmt
;
270 ** And to get the latest zone names into tzname. . .
272 for (i
= 0; i
< sp
->typecnt
; ++i
) {
273 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
275 tzname
[ttisp
->tt_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
277 for (i
= 0; i
< sp
->timecnt
; ++i
) {
278 register const struct ttinfo
* const ttisp
=
282 tzname
[ttisp
->tt_isdst
] =
283 &sp
->chars
[ttisp
->tt_abbrind
];
287 if (!ttisp
->tt_isdst
)
288 timezone
= -(ttisp
->tt_gmtoff
);
289 #endif /* defined USG_COMPAT */
292 altzone
= -(ttisp
->tt_gmtoff
);
293 #endif /* defined ALTZONE */
296 ** Finally, scrub the abbreviations.
297 ** First, replace bogus characters.
299 for (i
= 0; i
< sp
->charcnt
; ++i
)
300 if (strchr(TZ_ABBR_CHAR_SET
, sp
->chars
[i
]) == NULL
)
301 sp
->chars
[i
] = TZ_ABBR_ERR_CHAR
;
303 ** Second, truncate long abbreviations.
305 for (i
= 0; i
< sp
->typecnt
; ++i
) {
306 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
307 register char * cp
= &sp
->chars
[ttisp
->tt_abbrind
];
309 if (strlen(cp
) > TZ_ABBR_MAX_LEN
&&
310 strcmp(cp
, GRANDPARENTED
) != 0)
311 *(cp
+ TZ_ABBR_MAX_LEN
) = '\0';
316 differ_by_repeat(const time_t t1
, const time_t t0
)
318 if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
320 return t1
- t0
== SECSPERREPEAT
;
324 tzload(register const char *name
, register struct state
*const sp
,
325 register const int doextend
)
327 register const char * p
;
333 struct tzhead tzhead
;
334 char buf
[2 * sizeof(struct tzhead
) +
339 register u_t
* const up
= malloc(sizeof *up
);
340 #else /* !defined ALL_STATE */
342 register u_t
* const up
= &u
;
343 #endif /* !defined ALL_STATE */
345 sp
->goback
= sp
->goahead
= FALSE
;
350 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
353 register int doaccess
;
355 ** Section 4.9.1 of the C standard says that
356 ** "FILENAME_MAX expands to an integral constant expression
357 ** that is the size needed for an array of char large enough
358 ** to hold the longest file name string that the implementation
359 ** guarantees can be opened."
361 char fullname
[FILENAME_MAX
+ 1];
365 doaccess
= name
[0] == '/';
367 if ((p
= TZDIR
) == NULL
)
369 if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
371 (void) strcpy(fullname
, p
);
372 (void) strcat(fullname
, "/");
373 (void) strcat(fullname
, name
);
375 ** Set doaccess if '.' (as in "../") shows up in name.
377 if (strchr(name
, '.') != NULL
)
381 if (doaccess
&& access(name
, R_OK
) != 0)
383 if ((fid
= open(name
, OPEN_MODE
)) == -1)
386 nread
= read(fid
, up
->buf
, sizeof up
->buf
);
387 if (close(fid
) < 0 || nread
<= 0)
389 for (stored
= 4; stored
<= 8; stored
*= 2) {
394 ttisstdcnt
= (int) detzcode(up
->tzhead
.tzh_ttisstdcnt
);
395 ttisgmtcnt
= (int) detzcode(up
->tzhead
.tzh_ttisgmtcnt
);
396 sp
->leapcnt
= (int) detzcode(up
->tzhead
.tzh_leapcnt
);
397 sp
->timecnt
= (int) detzcode(up
->tzhead
.tzh_timecnt
);
398 sp
->typecnt
= (int) detzcode(up
->tzhead
.tzh_typecnt
);
399 sp
->charcnt
= (int) detzcode(up
->tzhead
.tzh_charcnt
);
400 p
= up
->tzhead
.tzh_charcnt
+ sizeof up
->tzhead
.tzh_charcnt
;
401 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
402 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
403 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
404 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
405 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
406 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
408 if (nread
- (p
- up
->buf
) <
409 sp
->timecnt
* stored
+ /* ats */
410 sp
->timecnt
+ /* types */
411 sp
->typecnt
* 6 + /* ttinfos */
412 sp
->charcnt
+ /* chars */
413 sp
->leapcnt
* (stored
+ 4) + /* lsinfos */
414 ttisstdcnt
+ /* ttisstds */
415 ttisgmtcnt
) /* ttisgmts */
418 for (i
= 0; i
< sp
->timecnt
; ++i
) {
420 = stored
== 4 ? detzcode(p
) : detzcode64(p
);
421 sp
->types
[i
] = ((TYPE_SIGNED(time_t)
424 && at
<= time_t_max
);
426 if (i
&& !timecnt
&& at
!= time_t_min
) {
428 ** Keep the earlier record, but tweak
429 ** it so that it starts with the
430 ** minimum time_t value.
432 sp
->types
[i
- 1] = 1;
433 sp
->ats
[timecnt
++] = time_t_min
;
435 sp
->ats
[timecnt
++] = at
;
440 for (i
= 0; i
< sp
->timecnt
; ++i
) {
441 unsigned char typ
= *p
++;
442 if (sp
->typecnt
<= typ
)
445 sp
->types
[timecnt
++] = typ
;
447 sp
->timecnt
= timecnt
;
448 for (i
= 0; i
< sp
->typecnt
; ++i
) {
449 register struct ttinfo
* ttisp
;
451 ttisp
= &sp
->ttis
[i
];
452 ttisp
->tt_gmtoff
= detzcode(p
);
454 ttisp
->tt_isdst
= (unsigned char) *p
++;
455 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
457 ttisp
->tt_abbrind
= (unsigned char) *p
++;
458 if (ttisp
->tt_abbrind
< 0 ||
459 ttisp
->tt_abbrind
> sp
->charcnt
)
462 for (i
= 0; i
< sp
->charcnt
; ++i
)
464 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
465 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
466 register struct lsinfo
* lsisp
;
468 lsisp
= &sp
->lsis
[i
];
469 lsisp
->ls_trans
= (stored
== 4) ?
470 detzcode(p
) : detzcode64(p
);
472 lsisp
->ls_corr
= detzcode(p
);
475 for (i
= 0; i
< sp
->typecnt
; ++i
) {
476 register struct ttinfo
* ttisp
;
478 ttisp
= &sp
->ttis
[i
];
480 ttisp
->tt_ttisstd
= FALSE
;
482 ttisp
->tt_ttisstd
= *p
++;
483 if (ttisp
->tt_ttisstd
!= TRUE
&&
484 ttisp
->tt_ttisstd
!= FALSE
)
488 for (i
= 0; i
< sp
->typecnt
; ++i
) {
489 register struct ttinfo
* ttisp
;
491 ttisp
= &sp
->ttis
[i
];
493 ttisp
->tt_ttisgmt
= FALSE
;
495 ttisp
->tt_ttisgmt
= *p
++;
496 if (ttisp
->tt_ttisgmt
!= TRUE
&&
497 ttisp
->tt_ttisgmt
!= FALSE
)
502 ** If this is an old file, we're done.
504 if (up
->tzhead
.tzh_version
[0] == '\0')
506 nread
-= p
- up
->buf
;
507 for (i
= 0; i
< nread
; ++i
)
510 ** If this is a signed narrow time_t system, we're done.
512 if (TYPE_SIGNED(time_t) && stored
>= (int) sizeof(time_t))
515 if (doextend
&& nread
> 2 &&
516 up
->buf
[0] == '\n' && up
->buf
[nread
- 1] == '\n' &&
517 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
521 up
->buf
[nread
- 1] = '\0';
522 result
= tzparse(&up
->buf
[1], &ts
, FALSE
);
523 if (result
== 0 && ts
.typecnt
== 2 &&
524 sp
->charcnt
+ ts
.charcnt
<= TZ_MAX_CHARS
) {
525 for (i
= 0; i
< 2; ++i
)
526 ts
.ttis
[i
].tt_abbrind
+=
528 for (i
= 0; i
< ts
.charcnt
; ++i
)
529 sp
->chars
[sp
->charcnt
++] =
532 while (i
< ts
.timecnt
&&
534 sp
->ats
[sp
->timecnt
- 1])
536 while (i
< ts
.timecnt
&&
537 sp
->timecnt
< TZ_MAX_TIMES
) {
538 sp
->ats
[sp
->timecnt
] =
540 sp
->types
[sp
->timecnt
] =
546 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
547 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
550 if (sp
->timecnt
> 1) {
551 for (i
= 1; i
< sp
->timecnt
; ++i
)
552 if (typesequiv(sp
, sp
->types
[i
], sp
->types
[0]) &&
553 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0])) {
557 for (i
= sp
->timecnt
- 2; i
>= 0; --i
)
558 if (typesequiv(sp
, sp
->types
[sp
->timecnt
- 1],
560 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
567 ** If type 0 is is unused in transitions,
568 ** it's the type to use for early times.
570 for (i
= 0; i
< sp
->typecnt
; ++i
)
571 if (sp
->types
[i
] == 0)
573 i
= (i
>= sp
->typecnt
) ? 0 : -1;
576 ** if there are transition times
577 ** and the first transition is to a daylight time
578 ** find the standard type less than and closest to
579 ** the type of the first transition.
581 if (i
< 0 && sp
->timecnt
> 0 && sp
->ttis
[sp
->types
[0]].tt_isdst
) {
584 if (!sp
->ttis
[i
].tt_isdst
)
588 ** If no result yet, find the first standard type.
589 ** If there is none, punt to type zero.
593 while (sp
->ttis
[i
].tt_isdst
)
594 if (++i
>= sp
->typecnt
) {
602 #endif /* defined ALL_STATE */
607 #endif /* defined ALL_STATE */
612 typesequiv(const struct state
*const sp
, const int a
, const int b
)
617 a
< 0 || a
>= sp
->typecnt
||
618 b
< 0 || b
>= sp
->typecnt
)
621 register const struct ttinfo
* ap
= &sp
->ttis
[a
];
622 register const struct ttinfo
* bp
= &sp
->ttis
[b
];
623 result
= ap
->tt_gmtoff
== bp
->tt_gmtoff
&&
624 ap
->tt_isdst
== bp
->tt_isdst
&&
625 ap
->tt_ttisstd
== bp
->tt_ttisstd
&&
626 ap
->tt_ttisgmt
== bp
->tt_ttisgmt
&&
627 strcmp(&sp
->chars
[ap
->tt_abbrind
],
628 &sp
->chars
[bp
->tt_abbrind
]) == 0;
633 static const int mon_lengths
[2][MONSPERYEAR
] = {
634 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
635 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
638 static const int year_lengths
[2] = {
639 DAYSPERNYEAR
, DAYSPERLYEAR
643 ** Given a pointer into a time zone string, scan until a character that is not
644 ** a valid character in a zone name is found. Return a pointer to that
649 getzname(register const char *strp
)
653 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
660 ** Given a pointer into an extended time zone string, scan until the ending
661 ** delimiter of the zone name is located. Return a pointer to the delimiter.
663 ** As with getzname above, the legal character set is actually quite
664 ** restricted, with other characters producing undefined results.
665 ** We don't do any checking here; checking is done later in common-case code.
669 getqzname(register const char *strp
, const int delim
)
673 while ((c
= *strp
) != '\0' && c
!= delim
)
679 ** Given a pointer into a time zone string, extract a number from that string.
680 ** Check that the number is within a specified range; if it is not, return
682 ** Otherwise, return a pointer to the first character not part of the number.
686 getnum(register const char *strp
, int *const nump
, const int min
, const int max
)
691 if (strp
== NULL
|| !is_digit(c
= *strp
))
695 num
= num
* 10 + (c
- '0');
697 return NULL
; /* illegal value */
699 } while (is_digit(c
));
701 return NULL
; /* illegal value */
707 ** Given a pointer into a time zone string, extract a number of seconds,
708 ** in hh[:mm[:ss]] form, from the string.
709 ** If any error occurs, return NULL.
710 ** Otherwise, return a pointer to the first character not part of the number
715 getsecs(register const char *strp
, int_fast32_t *const secsp
)
720 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
721 ** "M10.4.6/26", which does not conform to Posix,
722 ** but which specifies the equivalent of
723 ** ``02:00 on the first Sunday on or after 23 Oct''.
725 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
728 *secsp
= num
* (int_fast32_t) SECSPERHOUR
;
731 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
734 *secsp
+= num
* SECSPERMIN
;
737 /* `SECSPERMIN' allows for leap seconds. */
738 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
748 ** Given a pointer into a time zone string, extract an offset, in
749 ** [+-]hh[:mm[:ss]] form, from the string.
750 ** If any error occurs, return NULL.
751 ** Otherwise, return a pointer to the first character not part of the time.
755 getoffset(register const char *strp
, int_fast32_t *const offsetp
)
757 register int neg
= 0;
762 } else if (*strp
== '+')
764 strp
= getsecs(strp
, offsetp
);
766 return NULL
; /* illegal time */
768 *offsetp
= -*offsetp
;
773 ** Given a pointer into a time zone string, extract a rule in the form
774 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
775 ** If a valid rule is not found, return NULL.
776 ** Otherwise, return a pointer to the first character not part of the rule.
780 getrule(const char *strp
, register struct rule
*const rulep
)
786 rulep
->r_type
= JULIAN_DAY
;
788 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
789 } else if (*strp
== 'M') {
793 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
795 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
800 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
805 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
806 } else if (is_digit(*strp
)) {
810 rulep
->r_type
= DAY_OF_YEAR
;
811 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
812 } else return NULL
; /* invalid format */
820 strp
= getoffset(strp
, &rulep
->r_time
);
821 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
826 ** Given a year, a rule, and the offset from UT at the time that rule takes
827 ** effect, calculate the year-relative time that rule takes effect.
831 transtime(const int year
, register const struct rule
*const rulep
,
832 const int_fast32_t offset
)
834 register int leapyear
;
835 register int_fast32_t value
;
837 int d
, m1
, yy0
, yy1
, yy2
, dow
;
840 leapyear
= isleap(year
);
841 switch (rulep
->r_type
) {
845 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
847 ** In non-leap years, or if the day number is 59 or less, just
848 ** add SECSPERDAY times the day number-1 to the time of
849 ** January 1, midnight, to get the day.
851 value
= (rulep
->r_day
- 1) * SECSPERDAY
;
852 if (leapyear
&& rulep
->r_day
>= 60)
859 ** Just add SECSPERDAY times the day number to the time of
860 ** January 1, midnight, to get the day.
862 value
= rulep
->r_day
* SECSPERDAY
;
865 case MONTH_NTH_DAY_OF_WEEK
:
867 ** Mm.n.d - nth "dth day" of month m.
871 ** Use Zeller's Congruence to get day-of-week of first day of
874 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
875 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
878 dow
= ((26 * m1
- 2) / 10 +
879 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
884 ** "dow" is the day-of-week of the first day of the month. Get
885 ** the day-of-month (zero-origin) of the first "dow" day of the
888 d
= rulep
->r_day
- dow
;
891 for (i
= 1; i
< rulep
->r_week
; ++i
) {
892 if (d
+ DAYSPERWEEK
>=
893 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
899 ** "d" is the day-of-month (zero-origin) of the day we want.
901 value
= d
* SECSPERDAY
;
902 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
903 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
908 ** "value" is the year-relative time of 00:00:00 UT on the day in
909 ** question. To get the year-relative time of the specified local
910 ** time on that day, add the transition time and the current offset
913 return value
+ rulep
->r_time
+ offset
;
917 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
922 tzparse(const char *name
, register struct state
*const sp
,
925 const char * stdname
;
926 const char * dstname
;
929 int_fast32_t stdoffset
;
930 int_fast32_t dstoffset
;
932 register int load_result
;
933 static struct ttinfo zttinfo
;
938 stdlen
= strlen(name
); /* length of standard zone name */
940 if (stdlen
>= sizeof sp
->chars
)
941 stdlen
= (sizeof sp
->chars
) - 1;
947 name
= getqzname(name
, '>');
950 stdlen
= name
- stdname
;
953 name
= getzname(name
);
954 stdlen
= name
- stdname
;
958 name
= getoffset(name
, &stdoffset
);
962 load_result
= tzload(TZDEFRULES
, sp
, FALSE
);
963 if (load_result
!= 0)
964 sp
->leapcnt
= 0; /* so, we're off a little */
968 name
= getqzname(name
, '>');
971 dstlen
= name
- dstname
;
975 name
= getzname(name
);
976 dstlen
= name
- dstname
; /* length of DST zone name */
978 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
979 name
= getoffset(name
, &dstoffset
);
982 } else dstoffset
= stdoffset
- SECSPERHOUR
;
983 if (*name
== '\0' && load_result
!= 0)
984 name
= TZDEFRULESTRING
;
985 if (*name
== ',' || *name
== ';') {
989 register int yearlim
;
990 register int timecnt
;
994 if ((name
= getrule(name
, &start
)) == NULL
)
998 if ((name
= getrule(name
, &end
)) == NULL
)
1002 sp
->typecnt
= 2; /* standard time and DST */
1004 ** Two transitions per year, from EPOCH_YEAR forward.
1006 sp
->ttis
[0] = sp
->ttis
[1] = zttinfo
;
1007 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
1008 sp
->ttis
[0].tt_isdst
= 1;
1009 sp
->ttis
[0].tt_abbrind
= stdlen
+ 1;
1010 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
1011 sp
->ttis
[1].tt_isdst
= 0;
1012 sp
->ttis
[1].tt_abbrind
= 0;
1013 sp
->defaulttype
= 0;
1016 yearlim
= EPOCH_YEAR
+ YEARSPERREPEAT
;
1017 for (year
= EPOCH_YEAR
; year
< yearlim
; year
++) {
1019 starttime
= transtime(year
, &start
, stdoffset
),
1020 endtime
= transtime(year
, &end
, dstoffset
);
1022 yearsecs
= (year_lengths
[isleap(year
)]
1024 int reversed
= endtime
< starttime
;
1026 int_fast32_t swap
= starttime
;
1027 starttime
= endtime
;
1031 || (starttime
< endtime
1032 && (endtime
- starttime
1034 + (stdoffset
- dstoffset
))))) {
1035 if (TZ_MAX_TIMES
- 2 < timecnt
)
1037 yearlim
= year
+ YEARSPERREPEAT
+ 1;
1038 sp
->ats
[timecnt
] = janfirst
;
1039 if (increment_overflow_time
1040 (&sp
->ats
[timecnt
], starttime
))
1042 sp
->types
[timecnt
++] = reversed
;
1043 sp
->ats
[timecnt
] = janfirst
;
1044 if (increment_overflow_time
1045 (&sp
->ats
[timecnt
], endtime
))
1047 sp
->types
[timecnt
++] = !reversed
;
1049 if (increment_overflow_time(&janfirst
, yearsecs
))
1052 sp
->timecnt
= timecnt
;
1054 sp
->typecnt
= 1; /* Perpetual DST. */
1056 register int_fast32_t theirstdoffset
;
1057 register int_fast32_t theirdstoffset
;
1058 register int_fast32_t theiroffset
;
1066 ** Initial values of theirstdoffset and theirdstoffset.
1069 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1071 if (!sp
->ttis
[j
].tt_isdst
) {
1073 -sp
->ttis
[j
].tt_gmtoff
;
1078 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1080 if (sp
->ttis
[j
].tt_isdst
) {
1082 -sp
->ttis
[j
].tt_gmtoff
;
1087 ** Initially we're assumed to be in standard time.
1090 theiroffset
= theirstdoffset
;
1092 ** Now juggle transition times and types
1093 ** tracking offsets as you do.
1095 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1097 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1098 if (sp
->ttis
[j
].tt_ttisgmt
) {
1099 /* No adjustment to transition time */
1102 ** If summer time is in effect, and the
1103 ** transition time was not specified as
1104 ** standard time, add the summer time
1105 ** offset to the transition time;
1106 ** otherwise, add the standard time
1107 ** offset to the transition time.
1110 ** Transitions from DST to DDST
1111 ** will effectively disappear since
1112 ** POSIX provides for only one DST
1115 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1116 sp
->ats
[i
] += dstoffset
-
1119 sp
->ats
[i
] += stdoffset
-
1123 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1124 if (sp
->ttis
[j
].tt_isdst
)
1125 theirdstoffset
= theiroffset
;
1126 else theirstdoffset
= theiroffset
;
1129 ** Finally, fill in ttis.
1131 sp
->ttis
[0] = sp
->ttis
[1] = zttinfo
;
1132 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1133 sp
->ttis
[0].tt_isdst
= FALSE
;
1134 sp
->ttis
[0].tt_abbrind
= 0;
1135 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1136 sp
->ttis
[1].tt_isdst
= TRUE
;
1137 sp
->ttis
[1].tt_abbrind
= stdlen
+ 1;
1139 sp
->defaulttype
= 0;
1143 sp
->typecnt
= 1; /* only standard time */
1145 sp
->ttis
[0] = zttinfo
;
1146 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1147 sp
->ttis
[0].tt_isdst
= 0;
1148 sp
->ttis
[0].tt_abbrind
= 0;
1149 sp
->defaulttype
= 0;
1151 sp
->charcnt
= stdlen
+ 1;
1153 sp
->charcnt
+= dstlen
+ 1;
1154 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1157 (void) strncpy(cp
, stdname
, stdlen
);
1161 (void) strncpy(cp
, dstname
, dstlen
);
1162 *(cp
+ dstlen
) = '\0';
1168 gmtload(struct state
*const sp
)
1170 if (tzload(gmt
, sp
, TRUE
) != 0)
1171 (void) tzparse(gmt
, sp
, TRUE
);
1174 #ifndef STD_INSPIRED
1176 ** A non-static declaration of tzsetwall in a system header file
1177 ** may cause a warning about this upcoming static declaration...
1179 static void tzsetwall(void);
1182 void tzsetwall(void);
1183 #endif /* !defined STD_INSPIRED */
1192 if (lclptr
== NULL
) {
1193 lclptr
= malloc(sizeof *lclptr
);
1194 if (lclptr
== NULL
) {
1195 settzname(); /* all we can do */
1199 #endif /* defined ALL_STATE */
1200 if (tzload(NULL
, lclptr
, TRUE
) != 0)
1208 register const char * name
;
1210 name
= getenv("TZ");
1216 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1218 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1220 (void) strcpy(lcl_TZname
, name
);
1223 if (lclptr
== NULL
) {
1224 lclptr
= malloc(sizeof *lclptr
);
1225 if (lclptr
== NULL
) {
1226 settzname(); /* all we can do */
1230 #endif /* defined ALL_STATE */
1231 if (*name
== '\0') {
1233 ** User wants it fast rather than right.
1235 lclptr
->leapcnt
= 0; /* so, we're off a little */
1236 lclptr
->timecnt
= 0;
1237 lclptr
->typecnt
= 0;
1238 lclptr
->ttis
[0].tt_isdst
= 0;
1239 lclptr
->ttis
[0].tt_gmtoff
= 0;
1240 lclptr
->ttis
[0].tt_abbrind
= 0;
1241 (void) strcpy(lclptr
->chars
, gmt
);
1242 } else if (tzload(name
, lclptr
, TRUE
) != 0)
1243 if (name
[0] == ':' || tzparse(name
, lclptr
, FALSE
) != 0)
1244 (void) gmtload(lclptr
);
1249 ** The easy way to behave "as if no library function calls" localtime
1250 ** is to not call it--so we drop its guts into "localsub", which can be
1251 ** freely called. (And no, the PANS doesn't require the above behavior--
1252 ** but it *is* desirable.)
1254 ** The unused offset argument is for the benefit of mktime variants.
1259 localsub(const time_t *const timep
, const int_fast32_t offset
,
1260 struct tm
*const tmp
)
1262 register struct state
* sp
;
1263 register const struct ttinfo
* ttisp
;
1265 register struct tm
* result
;
1266 const time_t t
= *timep
;
1270 return gmtsub(timep
, offset
, tmp
);
1271 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1272 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1274 register time_t seconds
;
1275 register time_t years
;
1278 seconds
= sp
->ats
[0] - t
;
1279 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1281 years
= (seconds
/ SECSPERREPEAT
+ 1) * YEARSPERREPEAT
;
1282 seconds
= years
* AVGSECSPERYEAR
;
1285 else newt
-= seconds
;
1286 if (newt
< sp
->ats
[0] ||
1287 newt
> sp
->ats
[sp
->timecnt
- 1])
1288 return NULL
; /* "cannot happen" */
1289 result
= localsub(&newt
, offset
, tmp
);
1290 if (result
== tmp
) {
1291 register time_t newy
;
1293 newy
= tmp
->tm_year
;
1297 tmp
->tm_year
= newy
;
1298 if (tmp
->tm_year
!= newy
)
1303 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1304 i
= sp
->defaulttype
;
1306 register int lo
= 1;
1307 register int hi
= sp
->timecnt
;
1310 register int mid
= (lo
+ hi
) >> 1;
1312 if (t
< sp
->ats
[mid
])
1316 i
= (int) sp
->types
[lo
- 1];
1318 ttisp
= &sp
->ttis
[i
];
1320 ** To get (wrong) behavior that's compatible with System V Release 2.0
1321 ** you'd replace the statement below with
1322 ** t += ttisp->tt_gmtoff;
1323 ** timesub(&t, 0L, sp, tmp);
1325 result
= timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1326 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1327 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1329 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1330 #endif /* defined TM_ZONE */
1335 localtime(const time_t *const timep
)
1338 return localsub(timep
, 0L, &tm
);
1342 ** Re-entrant version of localtime.
1346 localtime_r(const time_t *const timep
, struct tm
*tmp
)
1348 return localsub(timep
, 0L, tmp
);
1352 ** gmtsub is to gmtime as localsub is to localtime.
1356 gmtsub(const time_t *const timep
, const int_fast32_t offset
,
1357 struct tm
*const tmp
)
1359 register struct tm
* result
;
1364 gmtptr
= malloc(sizeof *gmtptr
);
1365 #endif /* defined ALL_STATE */
1369 result
= timesub(timep
, offset
, gmtptr
, tmp
);
1372 ** Could get fancy here and deliver something such as
1373 ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
1374 ** but this is no time for a treasure hunt.
1376 tmp
->TM_ZONE
= offset
? wildabbr
: gmtptr
? gmtptr
->chars
: gmt
;
1377 #endif /* defined TM_ZONE */
1382 gmtime(const time_t *const timep
)
1384 return gmtsub(timep
, 0L, &tm
);
1388 * Re-entrant version of gmtime.
1392 gmtime_r(const time_t *const timep
, struct tm
*tmp
)
1394 return gmtsub(timep
, 0L, tmp
);
1398 struct tm
* offtime(const time_t *const timep
, const long offset
);
1401 offtime(const time_t *const timep
, const long offset
)
1403 return gmtsub(timep
, offset
, &tm
);
1406 #endif /* defined STD_INSPIRED */
1409 ** Return the number of leap years through the end of the given year
1410 ** where, to make the math easy, the answer for year zero is defined as zero.
1414 leaps_thru_end_of(register const int y
)
1416 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1417 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1421 timesub(const time_t *const timep
, const int_fast32_t offset
,
1422 register const struct state
*const sp
,
1423 register struct tm
*const tmp
)
1425 register const struct lsinfo
* lp
;
1426 register time_t tdays
;
1427 register int idays
; /* unsigned would be so 2003 */
1428 register int_fast64_t rem
;
1430 register const int * ip
;
1431 register int_fast64_t corr
;
1437 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1440 if (*timep
>= lp
->ls_trans
) {
1441 if (*timep
== lp
->ls_trans
) {
1442 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1443 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1446 sp
->lsis
[i
].ls_trans
==
1447 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1448 sp
->lsis
[i
].ls_corr
==
1449 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1459 tdays
= *timep
/ SECSPERDAY
;
1460 rem
= *timep
- tdays
* SECSPERDAY
;
1461 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1463 register time_t tdelta
;
1464 register int idelta
;
1465 register int leapdays
;
1467 tdelta
= tdays
/ DAYSPERLYEAR
;
1468 if (! ((! TYPE_SIGNED(time_t) || INT_MIN
<= tdelta
)
1469 && tdelta
<= INT_MAX
))
1473 idelta
= (tdays
< 0) ? -1 : 1;
1475 if (increment_overflow(&newy
, idelta
))
1477 leapdays
= leaps_thru_end_of(newy
- 1) -
1478 leaps_thru_end_of(y
- 1);
1479 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
1484 register int_fast32_t seconds
;
1486 seconds
= tdays
* SECSPERDAY
;
1487 tdays
= seconds
/ SECSPERDAY
;
1488 rem
+= seconds
- tdays
* SECSPERDAY
;
1491 ** Given the range, we can now fearlessly cast...
1494 rem
+= offset
- corr
;
1499 while (rem
>= SECSPERDAY
) {
1504 if (increment_overflow(&y
, -1))
1506 idays
+= year_lengths
[isleap(y
)];
1508 while (idays
>= year_lengths
[isleap(y
)]) {
1509 idays
-= year_lengths
[isleap(y
)];
1510 if (increment_overflow(&y
, 1))
1514 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1516 tmp
->tm_yday
= idays
;
1518 ** The "extra" mods below avoid overflow problems.
1520 tmp
->tm_wday
= EPOCH_WDAY
+
1521 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
1522 (DAYSPERNYEAR
% DAYSPERWEEK
) +
1523 leaps_thru_end_of(y
- 1) -
1524 leaps_thru_end_of(EPOCH_YEAR
- 1) +
1526 tmp
->tm_wday
%= DAYSPERWEEK
;
1527 if (tmp
->tm_wday
< 0)
1528 tmp
->tm_wday
+= DAYSPERWEEK
;
1529 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1531 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1533 ** A positive leap second requires a special
1534 ** representation. This uses "... ??:59:60" et seq.
1536 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1537 ip
= mon_lengths
[isleap(y
)];
1538 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1539 idays
-= ip
[tmp
->tm_mon
];
1540 tmp
->tm_mday
= (int) (idays
+ 1);
1543 tmp
->TM_GMTOFF
= offset
;
1544 #endif /* defined TM_GMTOFF */
1549 ctime(const time_t *const timep
)
1552 ** Section 4.12.3.2 of X3.159-1989 requires that
1553 ** The ctime function converts the calendar time pointed to by timer
1554 ** to local time in the form of a string. It is equivalent to
1555 ** asctime(localtime(timer))
1557 return asctime(localtime(timep
));
1561 ctime_r(const time_t *const timep
, char *buf
)
1565 return asctime_r(localtime_r(timep
, &mytm
), buf
);
1569 ** Adapted from code provided by Robert Elz, who writes:
1570 ** The "best" way to do mktime I think is based on an idea of Bob
1571 ** Kridle's (so its said...) from a long time ago.
1572 ** It does a binary search of the time_t space. Since time_t's are
1573 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1574 ** would still be very reasonable).
1579 #endif /* !defined WRONG */
1582 ** Normalize logic courtesy Paul Eggert.
1586 increment_overflow(int *const ip
, int j
)
1588 register int const i
= *ip
;
1591 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1592 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1593 ** If i < 0 there can only be overflow if i + j < INT_MIN
1594 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1596 if ((i
>= 0) ? (j
> INT_MAX
- i
) : (j
< INT_MIN
- i
))
1603 increment_overflow32(int_fast32_t *const lp
, int const m
)
1605 register int_fast32_t const l
= *lp
;
1607 if ((l
>= 0) ? (m
> INT_FAST32_MAX
- l
) : (m
< INT_FAST32_MIN
- l
))
1614 increment_overflow_time(time_t *tp
, int_fast32_t j
)
1618 ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
1619 ** except that it does the right thing even if *tp + j would overflow.
1622 ? (TYPE_SIGNED(time_t) ? time_t_min
- j
<= *tp
: -1 - j
< *tp
)
1623 : *tp
<= time_t_max
- j
))
1630 normalize_overflow(int *const tensptr
, int *const unitsptr
, const int base
)
1632 register int tensdelta
;
1634 tensdelta
= (*unitsptr
>= 0) ?
1635 (*unitsptr
/ base
) :
1636 (-1 - (-1 - *unitsptr
) / base
);
1637 *unitsptr
-= tensdelta
* base
;
1638 return increment_overflow(tensptr
, tensdelta
);
1642 normalize_overflow32(int_fast32_t *const tensptr
, int *const unitsptr
,
1645 register int tensdelta
;
1647 tensdelta
= (*unitsptr
>= 0) ?
1648 (*unitsptr
/ base
) :
1649 (-1 - (-1 - *unitsptr
) / base
);
1650 *unitsptr
-= tensdelta
* base
;
1651 return increment_overflow32(tensptr
, tensdelta
);
1655 tmcomp(register const struct tm
*const atmp
,
1656 register const struct tm
*const btmp
)
1658 register int result
;
1660 if (atmp
->tm_year
!= btmp
->tm_year
)
1661 return atmp
->tm_year
< btmp
->tm_year
? -1 : 1;
1662 if ((result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1663 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1664 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1665 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1666 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1671 time2sub(struct tm
*const tmp
,
1672 struct tm
*(*const funcp
)(const time_t *, int_fast32_t, struct tm
*),
1673 const int_fast32_t offset
,
1675 const int do_norm_secs
)
1677 register const struct state
* sp
;
1680 register int saved_seconds
;
1681 register int_fast32_t li
;
1687 struct tm yourtm
, mytm
;
1692 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1696 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1698 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1701 if (normalize_overflow32(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1704 ** Turn y into an actual year number for now.
1705 ** It is converted back to an offset from TM_YEAR_BASE later.
1707 if (increment_overflow32(&y
, TM_YEAR_BASE
))
1709 while (yourtm
.tm_mday
<= 0) {
1710 if (increment_overflow32(&y
, -1))
1712 li
= y
+ (1 < yourtm
.tm_mon
);
1713 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1715 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1716 li
= y
+ (1 < yourtm
.tm_mon
);
1717 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1718 if (increment_overflow32(&y
, 1))
1722 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1723 if (yourtm
.tm_mday
<= i
)
1725 yourtm
.tm_mday
-= i
;
1726 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1728 if (increment_overflow32(&y
, 1))
1732 if (increment_overflow32(&y
, -TM_YEAR_BASE
))
1735 if (yourtm
.tm_year
!= y
)
1737 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1739 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1741 ** We can't set tm_sec to 0, because that might push the
1742 ** time below the minimum representable time.
1743 ** Set tm_sec to 59 instead.
1744 ** This assumes that the minimum representable time is
1745 ** not in the same minute that a leap second was deleted from,
1746 ** which is a safer assumption than using 58 would be.
1748 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1750 saved_seconds
= yourtm
.tm_sec
;
1751 yourtm
.tm_sec
= SECSPERMIN
- 1;
1753 saved_seconds
= yourtm
.tm_sec
;
1757 ** Do a binary search (this works whatever time_t's type is).
1759 if (!TYPE_SIGNED(time_t)) {
1764 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
1769 t
= lo
/ 2 + hi
/ 2;
1774 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
1776 ** Assume that t is too extreme to be represented in
1777 ** a struct tm; arrange things so that it is less
1778 ** extreme on the next pass.
1780 dir
= (t
> 0) ? 1 : -1;
1781 } else dir
= tmcomp(&mytm
, &yourtm
);
1784 if (t
== time_t_max
)
1788 } else if (t
== hi
) {
1789 if (t
== time_t_min
)
1801 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1804 ** Right time, wrong type.
1805 ** Hunt for right time, right type.
1806 ** It's okay to guess wrong since the guess
1809 sp
= (const struct state
*)
1810 ((funcp
== localsub
) ? lclptr
: gmtptr
);
1813 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1814 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1816 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1817 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
1819 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
1820 sp
->ttis
[i
].tt_gmtoff
;
1821 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
1823 if (tmcomp(&mytm
, &yourtm
) != 0)
1825 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
1837 newt
= t
+ saved_seconds
;
1838 if ((newt
< t
) != (saved_seconds
< 0))
1841 if ((*funcp
)(&t
, offset
, tmp
))
1847 time2(struct tm
* const tmp
,
1848 struct tm
* (*const funcp
)(const time_t *, int_fast32_t, struct tm
*),
1849 const int_fast32_t offset
,
1855 ** First try without normalization of seconds
1856 ** (in case tm_sec contains a value associated with a leap second).
1857 ** If that fails, try with normalization of seconds.
1859 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
);
1860 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
);
1864 time1(struct tm
*const tmp
,
1865 struct tm
*(*const funcp
) (const time_t *, int_fast32_t, struct tm
*),
1866 const int_fast32_t offset
)
1869 register const struct state
* sp
;
1870 register int samei
, otheri
;
1871 register int sameind
, otherind
;
1874 int seen
[TZ_MAX_TYPES
];
1875 int types
[TZ_MAX_TYPES
];
1882 if (tmp
->tm_isdst
> 1)
1884 t
= time2(tmp
, funcp
, offset
, &okay
);
1887 if (tmp
->tm_isdst
< 0)
1890 ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
1892 tmp
->tm_isdst
= 0; /* reset to std and try again */
1895 #endif /* !defined PCTS */
1897 ** We're supposed to assume that somebody took a time of one type
1898 ** and did some math on it that yielded a "struct tm" that's bad.
1899 ** We try to divine the type they started from and adjust to the
1902 sp
= (const struct state
*) ((funcp
== localsub
) ? lclptr
: gmtptr
);
1905 for (i
= 0; i
< sp
->typecnt
; ++i
)
1908 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
1909 if (!seen
[sp
->types
[i
]]) {
1910 seen
[sp
->types
[i
]] = TRUE
;
1911 types
[nseen
++] = sp
->types
[i
];
1913 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
1914 samei
= types
[sameind
];
1915 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
1917 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
1918 otheri
= types
[otherind
];
1919 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
1921 tmp
->tm_sec
+= sp
->ttis
[otheri
].tt_gmtoff
-
1922 sp
->ttis
[samei
].tt_gmtoff
;
1923 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1924 t
= time2(tmp
, funcp
, offset
, &okay
);
1927 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
1928 sp
->ttis
[samei
].tt_gmtoff
;
1929 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1936 mktime(struct tm
*const tmp
)
1939 return time1(tmp
, localsub
, 0L);
1943 time_t timelocal(struct tm
*const tmp
);
1946 timelocal(struct tm
*const tmp
)
1949 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
1953 time_t timegm(struct tm
*const tmp
);
1956 timegm(struct tm
*const tmp
)
1960 return time1(tmp
, gmtsub
, 0L);
1963 time_t timeoff(struct tm
*const tmp
, const long offset
);
1966 timeoff(struct tm
*const tmp
, const long offset
)
1970 return time1(tmp
, gmtsub
, offset
);
1973 #endif /* defined STD_INSPIRED */
1978 ** The following is supplied for compatibility with
1979 ** previous versions of the CMUCS runtime library.
1983 gtime(struct tm
*const tmp
)
1985 const time_t t
= mktime(tmp
);
1992 #endif /* defined CMUCS */
1995 ** XXX--is the below the right way to conditionalize??
2001 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2002 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2003 ** is not the case if we are accounting for leap seconds.
2004 ** So, we provide the following conversion routines for use
2005 ** when exchanging timestamps with POSIX conforming systems.
2009 leapcorr(time_t *timep
)
2011 register struct state
* sp
;
2012 register struct lsinfo
* lp
;
2019 if (*timep
>= lp
->ls_trans
)
2025 time_t time2posix(time_t t
);
2028 time2posix(time_t t
)
2031 return t
- leapcorr(&t
);
2034 time_t posix2time(time_t t
);
2037 posix2time(time_t t
)
2044 ** For a positive leap second hit, the result
2045 ** is not unique. For a negative leap second
2046 ** hit, the corresponding time doesn't exist,
2047 ** so we return an adjacent second.
2049 x
= t
+ leapcorr(&t
);
2050 y
= x
- leapcorr(&x
);
2054 y
= x
- leapcorr(&x
);
2061 y
= x
- leapcorr(&x
);
2069 #endif /* defined STD_INSPIRED */