1 /* $NetBSD: localtime.c,v 1.98 2015/10/09 17:21:45 christos Exp $ */
4 ** This file is in the public domain, so clarified as of
5 ** 1996-06-05 by Arthur David Olson.
9 #if defined(LIBC_SCCS) && !defined(lint)
11 static char elsieid
[] = "@(#)localtime.c 8.17";
13 __RCSID("$NetBSD: localtime.c,v 1.98 2015/10/09 17:21:45 christos Exp $");
15 #endif /* LIBC_SCCS and not lint */
18 ** Leap second handling from Bradley White.
19 ** POSIX-style TZ environment variable handling from Guy Harris.
24 #include "namespace.h"
26 #define LOCALTIME_IMPLEMENTATION
31 #include "reentrant.h"
34 # define NETBSD_INSPIRED_EXTERN
36 # define NETBSD_INSPIRED_EXTERN static
39 #if defined(__weak_alias)
40 __weak_alias(daylight
,_daylight
)
41 __weak_alias(tzname
,_tzname
)
44 #ifndef TZ_ABBR_MAX_LEN
45 #define TZ_ABBR_MAX_LEN 16
46 #endif /* !defined TZ_ABBR_MAX_LEN */
48 #ifndef TZ_ABBR_CHAR_SET
49 #define TZ_ABBR_CHAR_SET \
50 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
51 #endif /* !defined TZ_ABBR_CHAR_SET */
53 #ifndef TZ_ABBR_ERR_CHAR
54 #define TZ_ABBR_ERR_CHAR '_'
55 #endif /* !defined TZ_ABBR_ERR_CHAR */
58 ** SunOS 4.1.1 headers lack O_BINARY.
62 #define OPEN_MODE (O_RDONLY | O_BINARY | O_CLOEXEC)
63 #endif /* defined O_BINARY */
65 #define OPEN_MODE (O_RDONLY | O_CLOEXEC)
66 #endif /* !defined O_BINARY */
70 ** Someone might make incorrect use of a time zone abbreviation:
71 ** 1. They might reference tzname[0] before calling tzset (explicitly
73 ** 2. They might reference tzname[1] before calling tzset (explicitly
75 ** 3. They might reference tzname[1] after setting to a time zone
76 ** in which Daylight Saving Time is never observed.
77 ** 4. They might reference tzname[0] after setting to a time zone
78 ** in which Standard Time is never observed.
79 ** 5. They might reference tm.TM_ZONE after calling offtime.
80 ** What's best to do in the above cases is open to debate;
81 ** for now, we just set things up so that in any of the five cases
82 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
83 ** string "tzname[0] used before set", and similarly for the other cases.
84 ** And another: initialize tzname[0] to "ERA", with an explanation in the
85 ** manual page of what this "time zone abbreviation" means (doing this so
86 ** that tzname[0] has the "normal" length of three characters).
89 #endif /* !defined WILDABBR */
91 static const char wildabbr
[] = WILDABBR
;
93 static const char gmt
[] = "GMT";
96 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
97 ** We default to US rules as of 1999-08-17.
98 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
99 ** implementation dependent; for historical reasons, US rules are a
102 #ifndef TZDEFRULESTRING
103 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
104 #endif /* !defined TZDEFDST */
106 struct ttinfo
{ /* time type information */
107 int_fast32_t tt_gmtoff
; /* UT offset in seconds */
108 bool tt_isdst
; /* used to set tm_isdst */
109 int tt_abbrind
; /* abbreviation list index */
110 bool tt_ttisstd
; /* transition is std time */
111 bool tt_ttisgmt
; /* transition is UT */
114 struct lsinfo
{ /* leap second information */
115 time_t ls_trans
; /* transition time */
116 int_fast64_t ls_corr
; /* correction to apply */
119 #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
120 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
123 #define MY_TZNAME_MAX TZNAME_MAX
124 #endif /* defined TZNAME_MAX */
126 #define MY_TZNAME_MAX 255
127 #endif /* !defined TZNAME_MAX */
129 #define state __state
137 time_t ats
[TZ_MAX_TIMES
];
138 unsigned char types
[TZ_MAX_TIMES
];
139 struct ttinfo ttis
[TZ_MAX_TYPES
];
140 char chars
[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1,
141 sizeof gmt
), (2 * (MY_TZNAME_MAX
+ 1)))];
142 struct lsinfo lsis
[TZ_MAX_LEAPS
];
143 int defaulttype
; /* for early times or if no transitions */
147 JULIAN_DAY
, /* Jn = Julian day */
148 DAY_OF_YEAR
, /* n = day of year */
149 MONTH_NTH_DAY_OF_WEEK
/* Mm.n.d = month, week, day of week */
153 enum r_type r_type
; /* type of rule */
154 int r_day
; /* day number of rule */
155 int r_week
; /* week number of rule */
156 int r_mon
; /* month number of rule */
157 int_fast32_t r_time
; /* transition time of rule */
160 static struct tm
*gmtsub(struct state
const *, time_t const *, int_fast32_t,
162 static bool increment_overflow(int *, int);
163 static bool increment_overflow_time(time_t *, int_fast32_t);
164 static bool normalize_overflow32(int_fast32_t *, int *, int);
165 static struct tm
*timesub(time_t const *, int_fast32_t, struct state
const *,
167 static bool typesequiv(struct state
const *, int, int);
168 static bool tzparse(char const *, struct state
*, bool);
170 static timezone_t lclptr
;
171 static timezone_t gmtptr
;
173 #ifndef TZ_STRLEN_MAX
174 #define TZ_STRLEN_MAX 255
175 #endif /* !defined TZ_STRLEN_MAX */
177 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
178 static int lcl_is_set
;
180 #if !defined(__LIBC12_SOURCE__)
182 __aconst
char * tzname
[2] = {
183 (__aconst
char *)__UNCONST(wildabbr
),
184 (__aconst
char *)__UNCONST(wildabbr
)
189 extern __aconst
char * tzname
[2];
194 static rwlock_t lcl_lock
= RWLOCK_INITIALIZER
;
198 ** Section 4.12.3 of X3.159-1989 requires that
199 ** Except for the strftime function, these functions [asctime,
200 ** ctime, gmtime, localtime] return values in one of two static
201 ** objects: a broken-down time structure and an array of char.
202 ** Thanks to Paul Eggert for noting this.
208 #if !defined(__LIBC12_SOURCE__)
213 extern long timezone
__RENAME(__timezone13
);
215 #endif /* defined USG_COMPAT */
219 #endif /* defined ALTZONE */
221 /* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
223 init_ttinfo(struct ttinfo
*s
, int_fast32_t gmtoff
, bool isdst
, int abbrind
)
225 s
->tt_gmtoff
= gmtoff
;
227 s
->tt_abbrind
= abbrind
;
228 s
->tt_ttisstd
= false;
229 s
->tt_ttisgmt
= false;
233 detzcode(const char *const codep
)
237 int_fast32_t one
= 1;
238 int_fast32_t halfmaxval
= one
<< (32 - 2);
239 int_fast32_t maxval
= halfmaxval
- 1 + halfmaxval
;
240 int_fast32_t minval
= -1 - maxval
;
242 result
= codep
[0] & 0x7f;
243 for (i
= 1; i
< 4; ++i
)
244 result
= (result
<< 8) | (codep
[i
] & 0xff);
246 if (codep
[0] & 0x80) {
247 /* Do two's-complement negation even on non-two's-complement machines.
248 If the result would be minval - 1, return minval. */
249 result
-= !TWOS_COMPLEMENT(int_fast32_t) && result
!= 0;
256 detzcode64(const char *const codep
)
260 int_fast64_t one
= 1;
261 int_fast64_t halfmaxval
= one
<< (64 - 2);
262 int_fast64_t maxval
= halfmaxval
- 1 + halfmaxval
;
263 int_fast64_t minval
= -TWOS_COMPLEMENT(int_fast64_t) - maxval
;
265 result
= codep
[0] & 0x7f;
266 for (i
= 1; i
< 8; ++i
)
267 result
= (result
<< 8) | (codep
[i
] & 0xff);
269 if (codep
[0] & 0x80) {
270 /* Do two's-complement negation even on non-two's-complement machines.
271 If the result would be minval - 1, return minval. */
272 result
-= !TWOS_COMPLEMENT(int_fast64_t) && result
!= 0;
279 tzgetname(const timezone_t sp
, int isdst
)
282 for (i
= 0; i
< sp
->timecnt
; ++i
) {
283 const struct ttinfo
*const ttisp
= &sp
->ttis
[sp
->types
[i
]];
285 if (ttisp
->tt_isdst
== isdst
)
286 return &sp
->chars
[ttisp
->tt_abbrind
];
293 scrub_abbrs(struct state
*sp
)
298 ** First, replace bogus characters.
300 for (i
= 0; i
< sp
->charcnt
; ++i
)
301 if (strchr(TZ_ABBR_CHAR_SET
, sp
->chars
[i
]) == NULL
)
302 sp
->chars
[i
] = TZ_ABBR_ERR_CHAR
;
304 ** Second, truncate long abbreviations.
306 for (i
= 0; i
< sp
->typecnt
; ++i
) {
307 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
308 char * cp
= &sp
->chars
[ttisp
->tt_abbrind
];
310 if (strlen(cp
) > TZ_ABBR_MAX_LEN
&&
311 strcmp(cp
, GRANDPARENTED
) != 0)
312 *(cp
+ TZ_ABBR_MAX_LEN
) = '\0';
317 update_tzname_etc(const struct state
*sp
, const struct ttinfo
*ttisp
)
319 tzname
[ttisp
->tt_isdst
] = __UNCONST(&sp
->chars
[ttisp
->tt_abbrind
]);
321 if (!ttisp
->tt_isdst
)
322 timezone
= - ttisp
->tt_gmtoff
;
326 altzone
= - ttisp
->tt_gmtoff
;
327 #endif /* defined ALTZONE */
333 timezone_t
const sp
= lclptr
;
336 tzname
[0] = (__aconst
char *)__UNCONST(wildabbr
);
337 tzname
[1] = (__aconst
char *)__UNCONST(wildabbr
);
341 #endif /* defined USG_COMPAT */
344 #endif /* defined ALTZONE */
346 tzname
[0] = tzname
[1] = (__aconst
char *)__UNCONST(gmt
);
350 ** And to get the latest zone names into tzname. . .
352 for (i
= 0; i
< sp
->typecnt
; ++i
)
353 update_tzname_etc(sp
, &sp
->ttis
[i
]);
355 for (i
= 0; i
< sp
->timecnt
; ++i
) {
356 const struct ttinfo
* const ttisp
= &sp
->ttis
[sp
->types
[i
]];
357 update_tzname_etc(sp
, ttisp
);
361 #endif /* defined USG_COMPAT */
366 differ_by_repeat(const time_t t1
, const time_t t0
)
368 if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
370 return (int_fast64_t)t1
- (int_fast64_t)t0
== SECSPERREPEAT
;
374 /* The first part of the buffer, interpreted as a header. */
375 struct tzhead tzhead
;
377 /* The entire buffer. */
378 char buf
[2 * sizeof(struct tzhead
) + 2 * sizeof (struct state
)
382 /* Local storage needed for 'tzloadbody'. */
383 union local_storage
{
384 /* The file name to be opened. */
385 char fullname
[FILENAME_MAX
+ 1];
387 /* The results of analyzing the file's contents after it is opened. */
389 /* The input buffer. */
390 union input_buffer u
;
392 /* A temporary state used for parsing a TZ string in the file. */
397 /* Load tz data from the file named NAME into *SP. Read extended
398 format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
399 success, an errno value on failure. */
401 tzloadbody(char const *name
, struct state
*sp
, bool doextend
,
402 union local_storage
*lsp
)
409 char *fullname
= lsp
->fullname
;
410 union input_buffer
*up
= &lsp
->u
.u
;
411 size_t tzheadsize
= sizeof(struct tzhead
);
413 sp
->goback
= sp
->goahead
= false;
423 doaccess
= name
[0] == '/';
425 char const *p
= TZDIR
;
428 if (sizeof lsp
->fullname
- 1 <= strlen(p
) + strlen(name
))
431 strcat(fullname
, "/");
432 strcat(fullname
, name
);
433 /* Set doaccess if '.' (as in "../") shows up in name. */
434 if (strchr(name
, '.'))
438 if (doaccess
&& access(name
, R_OK
) != 0)
441 fid
= open(name
, OPEN_MODE
);
444 nread
= read(fid
, up
->buf
, sizeof up
->buf
);
445 if (nread
< (ssize_t
)tzheadsize
) {
446 int err
= nread
< 0 ? errno
: EINVAL
;
452 for (stored
= 4; stored
<= 8; stored
*= 2) {
453 int_fast32_t ttisstdcnt
= detzcode(up
->tzhead
.tzh_ttisstdcnt
);
454 int_fast32_t ttisgmtcnt
= detzcode(up
->tzhead
.tzh_ttisgmtcnt
);
455 int_fast32_t leapcnt
= detzcode(up
->tzhead
.tzh_leapcnt
);
456 int_fast32_t timecnt
= detzcode(up
->tzhead
.tzh_timecnt
);
457 int_fast32_t typecnt
= detzcode(up
->tzhead
.tzh_typecnt
);
458 int_fast32_t charcnt
= detzcode(up
->tzhead
.tzh_charcnt
);
459 char const *p
= up
->buf
+ tzheadsize
;
460 if (! (0 <= leapcnt
&& leapcnt
< TZ_MAX_LEAPS
461 && 0 < typecnt
&& typecnt
< TZ_MAX_TYPES
462 && 0 <= timecnt
&& timecnt
< TZ_MAX_TIMES
463 && 0 <= charcnt
&& charcnt
< TZ_MAX_CHARS
464 && (ttisstdcnt
== typecnt
|| ttisstdcnt
== 0)
465 && (ttisgmtcnt
== typecnt
|| ttisgmtcnt
== 0)))
468 < (tzheadsize
/* struct tzhead */
469 + timecnt
* stored
/* ats */
470 + timecnt
/* types */
471 + typecnt
* 6 /* ttinfos */
472 + charcnt
/* chars */
473 + leapcnt
* (stored
+ 4) /* lsinfos */
474 + ttisstdcnt
/* ttisstds */
475 + ttisgmtcnt
)) /* ttisgmts */
477 sp
->leapcnt
= leapcnt
;
478 sp
->timecnt
= timecnt
;
479 sp
->typecnt
= typecnt
;
480 sp
->charcnt
= charcnt
;
482 /* Read transitions, discarding those out of time_t range.
483 But pretend the last transition before time_t_min
484 occurred at time_t_min. */
486 for (i
= 0; i
< sp
->timecnt
; ++i
) {
488 = stored
== 4 ? detzcode(p
) : detzcode64(p
);
489 sp
->types
[i
] = at
<= time_t_max
;
492 = ((TYPE_SIGNED(time_t) ?
493 at
< time_t_min
: at
< 0)
494 ? time_t_min
: (time_t)at
);
495 if (timecnt
&& attime
<= sp
->ats
[timecnt
- 1]) {
496 if (attime
< sp
->ats
[timecnt
- 1])
498 sp
->types
[i
- 1] = 0;
501 sp
->ats
[timecnt
++] = attime
;
507 for (i
= 0; i
< sp
->timecnt
; ++i
) {
508 unsigned char typ
= *p
++;
509 if (sp
->typecnt
<= typ
)
512 sp
->types
[timecnt
++] = typ
;
514 sp
->timecnt
= timecnt
;
515 for (i
= 0; i
< sp
->typecnt
; ++i
) {
516 struct ttinfo
* ttisp
;
517 unsigned char isdst
, abbrind
;
519 ttisp
= &sp
->ttis
[i
];
520 ttisp
->tt_gmtoff
= detzcode(p
);
525 ttisp
->tt_isdst
= isdst
;
527 if (! (abbrind
< sp
->charcnt
))
529 ttisp
->tt_abbrind
= abbrind
;
531 for (i
= 0; i
< sp
->charcnt
; ++i
)
533 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
535 /* Read leap seconds, discarding those out of time_t range. */
537 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
538 int_fast64_t tr
= stored
== 4 ? detzcode(p
) :
540 int_fast32_t corr
= detzcode(p
+ stored
);
542 if (tr
<= time_t_max
) {
543 time_t trans
= ((TYPE_SIGNED(time_t) ?
544 tr
< time_t_min
: tr
< 0)
545 ? time_t_min
: (time_t)tr
);
546 if (leapcnt
&& trans
<=
547 sp
->lsis
[leapcnt
- 1].ls_trans
) {
549 sp
->lsis
[leapcnt
- 1].ls_trans
)
553 sp
->lsis
[leapcnt
].ls_trans
= trans
;
554 sp
->lsis
[leapcnt
].ls_corr
= corr
;
558 sp
->leapcnt
= leapcnt
;
560 for (i
= 0; i
< sp
->typecnt
; ++i
) {
561 struct ttinfo
* ttisp
;
563 ttisp
= &sp
->ttis
[i
];
565 ttisp
->tt_ttisstd
= false;
567 if (*p
!= true && *p
!= false)
569 ttisp
->tt_ttisstd
= *p
++;
572 for (i
= 0; i
< sp
->typecnt
; ++i
) {
573 struct ttinfo
* ttisp
;
575 ttisp
= &sp
->ttis
[i
];
577 ttisp
->tt_ttisgmt
= false;
579 if (*p
!= true && *p
!= false)
581 ttisp
->tt_ttisgmt
= *p
++;
585 ** If this is an old file, we're done.
587 if (up
->tzhead
.tzh_version
[0] == '\0')
589 nread
-= p
- up
->buf
;
590 memmove(up
->buf
, p
, (size_t)nread
);
592 if (doextend
&& nread
> 2 &&
593 up
->buf
[0] == '\n' && up
->buf
[nread
- 1] == '\n' &&
594 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
595 struct state
*ts
= &lsp
->u
.st
;
597 up
->buf
[nread
- 1] = '\0';
598 if (tzparse(&up
->buf
[1], ts
, false)
599 && ts
->typecnt
== 2) {
601 /* Attempt to reuse existing abbreviations.
602 Without this, America/Anchorage would stop
603 working after 2037 when TZ_MAX_CHARS is 50, as
604 sp->charcnt equals 42 (for LMT CAT CAWT CAPT AHST
605 AHDT YST AKDT AKST) and ts->charcnt equals 10
606 (for AKST AKDT). Reusing means sp->charcnt can
607 stay 42 in this example. */
609 int charcnt
= sp
->charcnt
;
610 for (i
= 0; i
< 2; i
++) {
611 char *tsabbr
= ts
->chars
+ ts
->ttis
[i
].tt_abbrind
;
613 for (j
= 0; j
< charcnt
; j
++)
614 if (strcmp(sp
->chars
+ j
, tsabbr
) == 0) {
615 ts
->ttis
[i
].tt_abbrind
= j
;
619 if (! (j
< charcnt
)) {
620 int tsabbrlen
= strlen(tsabbr
);
621 if (j
+ tsabbrlen
< TZ_MAX_CHARS
) {
622 strcpy(sp
->chars
+ j
, tsabbr
);
623 charcnt
= j
+ tsabbrlen
+ 1;
624 ts
->ttis
[i
].tt_abbrind
= j
;
630 sp
->charcnt
= charcnt
;
631 for (i
= 0; i
< ts
->timecnt
; i
++)
632 if (sp
->ats
[sp
->timecnt
- 1] < ts
->ats
[i
])
634 while (i
< ts
->timecnt
635 && sp
->timecnt
< TZ_MAX_TIMES
) {
636 sp
->ats
[sp
->timecnt
] = ts
->ats
[i
];
637 sp
->types
[sp
->timecnt
] = (sp
->typecnt
642 sp
->ttis
[sp
->typecnt
++] = ts
->ttis
[0];
643 sp
->ttis
[sp
->typecnt
++] = ts
->ttis
[1];
647 if (sp
->timecnt
> 1) {
648 for (i
= 1; i
< sp
->timecnt
; ++i
)
649 if (typesequiv(sp
, sp
->types
[i
], sp
->types
[0]) &&
650 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0])) {
654 for (i
= sp
->timecnt
- 2; i
>= 0; --i
)
655 if (typesequiv(sp
, sp
->types
[sp
->timecnt
- 1],
657 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
664 ** If type 0 is is unused in transitions,
665 ** it's the type to use for early times.
667 for (i
= 0; i
< sp
->timecnt
; ++i
)
668 if (sp
->types
[i
] == 0)
670 i
= i
< sp
->timecnt
? -1 : 0;
673 ** if there are transition times
674 ** and the first transition is to a daylight time
675 ** find the standard type less than and closest to
676 ** the type of the first transition.
678 if (i
< 0 && sp
->timecnt
> 0 && sp
->ttis
[sp
->types
[0]].tt_isdst
) {
681 if (!sp
->ttis
[i
].tt_isdst
)
685 ** If no result yet, find the first standard type.
686 ** If there is none, punt to type zero.
690 while (sp
->ttis
[i
].tt_isdst
)
691 if (++i
>= sp
->typecnt
) {
700 /* Load tz data from the file named NAME into *SP. Read extended
701 format if DOEXTEND. Return 0 on success, an errno value on failure. */
703 tzload(char const *name
, struct state
*sp
, bool doextend
)
705 union local_storage
*lsp
= malloc(sizeof *lsp
);
709 int err
= tzloadbody(name
, sp
, doextend
, lsp
);
716 typesequiv(const struct state
*sp
, int a
, int b
)
721 a
< 0 || a
>= sp
->typecnt
||
722 b
< 0 || b
>= sp
->typecnt
)
725 const struct ttinfo
* ap
= &sp
->ttis
[a
];
726 const struct ttinfo
* bp
= &sp
->ttis
[b
];
727 result
= ap
->tt_gmtoff
== bp
->tt_gmtoff
&&
728 ap
->tt_isdst
== bp
->tt_isdst
&&
729 ap
->tt_ttisstd
== bp
->tt_ttisstd
&&
730 ap
->tt_ttisgmt
== bp
->tt_ttisgmt
&&
731 strcmp(&sp
->chars
[ap
->tt_abbrind
],
732 &sp
->chars
[bp
->tt_abbrind
]) == 0;
737 static const int mon_lengths
[2][MONSPERYEAR
] = {
738 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
739 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
742 static const int year_lengths
[2] = {
743 DAYSPERNYEAR
, DAYSPERLYEAR
747 ** Given a pointer into a time zone string, scan until a character that is not
748 ** a valid character in a zone name is found. Return a pointer to that
752 static const char * ATTRIBUTE_PURE
753 getzname(const char *strp
)
757 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
764 ** Given a pointer into an extended time zone string, scan until the ending
765 ** delimiter of the zone name is located. Return a pointer to the delimiter.
767 ** As with getzname above, the legal character set is actually quite
768 ** restricted, with other characters producing undefined results.
769 ** We don't do any checking here; checking is done later in common-case code.
772 static const char * ATTRIBUTE_PURE
773 getqzname(const char *strp
, const int delim
)
777 while ((c
= *strp
) != '\0' && c
!= delim
)
783 ** Given a pointer into a time zone string, extract a number from that string.
784 ** Check that the number is within a specified range; if it is not, return
786 ** Otherwise, return a pointer to the first character not part of the number.
790 getnum(const char *strp
, int *const nump
, const int min
, const int max
)
795 if (strp
== NULL
|| !is_digit(c
= *strp
)) {
801 num
= num
* 10 + (c
- '0');
804 return NULL
; /* illegal value */
807 } while (is_digit(c
));
810 return NULL
; /* illegal value */
817 ** Given a pointer into a time zone string, extract a number of seconds,
818 ** in hh[:mm[:ss]] form, from the string.
819 ** If any error occurs, return NULL.
820 ** Otherwise, return a pointer to the first character not part of the number
825 getsecs(const char *strp
, int_fast32_t *const secsp
)
830 ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
831 ** "M10.4.6/26", which does not conform to Posix,
832 ** but which specifies the equivalent of
833 ** "02:00 on the first Sunday on or after 23 Oct".
835 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
838 *secsp
= num
* (int_fast32_t) SECSPERHOUR
;
841 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
844 *secsp
+= num
* SECSPERMIN
;
847 /* 'SECSPERMIN' allows for leap seconds. */
848 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
858 ** Given a pointer into a time zone string, extract an offset, in
859 ** [+-]hh[:mm[:ss]] form, from the string.
860 ** If any error occurs, return NULL.
861 ** Otherwise, return a pointer to the first character not part of the time.
865 getoffset(const char *strp
, int_fast32_t *const offsetp
)
872 } else if (*strp
== '+')
874 strp
= getsecs(strp
, offsetp
);
876 return NULL
; /* illegal time */
878 *offsetp
= -*offsetp
;
883 ** Given a pointer into a time zone string, extract a rule in the form
884 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
885 ** If a valid rule is not found, return NULL.
886 ** Otherwise, return a pointer to the first character not part of the rule.
890 getrule(const char *strp
, struct rule
*const rulep
)
896 rulep
->r_type
= JULIAN_DAY
;
898 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
899 } else if (*strp
== 'M') {
903 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
905 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
910 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
915 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
916 } else if (is_digit(*strp
)) {
920 rulep
->r_type
= DAY_OF_YEAR
;
921 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
922 } else return NULL
; /* invalid format */
930 strp
= getoffset(strp
, &rulep
->r_time
);
931 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
936 ** Given a year, a rule, and the offset from UT at the time that rule takes
937 ** effect, calculate the year-relative time that rule takes effect.
940 static int_fast32_t ATTRIBUTE_PURE
941 transtime(const int year
, const struct rule
*const rulep
,
942 const int_fast32_t offset
)
947 int d
, m1
, yy0
, yy1
, yy2
, dow
;
950 leapyear
= isleap(year
);
951 switch (rulep
->r_type
) {
955 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
957 ** In non-leap years, or if the day number is 59 or less, just
958 ** add SECSPERDAY times the day number-1 to the time of
959 ** January 1, midnight, to get the day.
961 value
= (rulep
->r_day
- 1) * SECSPERDAY
;
962 if (leapyear
&& rulep
->r_day
>= 60)
969 ** Just add SECSPERDAY times the day number to the time of
970 ** January 1, midnight, to get the day.
972 value
= rulep
->r_day
* SECSPERDAY
;
975 case MONTH_NTH_DAY_OF_WEEK
:
977 ** Mm.n.d - nth "dth day" of month m.
981 ** Use Zeller's Congruence to get day-of-week of first day of
984 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
985 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
988 dow
= ((26 * m1
- 2) / 10 +
989 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
994 ** "dow" is the day-of-week of the first day of the month. Get
995 ** the day-of-month (zero-origin) of the first "dow" day of the
998 d
= rulep
->r_day
- dow
;
1001 for (i
= 1; i
< rulep
->r_week
; ++i
) {
1002 if (d
+ DAYSPERWEEK
>=
1003 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
1009 ** "d" is the day-of-month (zero-origin) of the day we want.
1011 value
= d
* SECSPERDAY
;
1012 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
1013 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
1018 ** "value" is the year-relative time of 00:00:00 UT on the day in
1019 ** question. To get the year-relative time of the specified local
1020 ** time on that day, add the transition time and the current offset
1023 return value
+ rulep
->r_time
+ offset
;
1027 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1032 tzparse(const char *name
, struct state
*sp
, bool lastditch
)
1034 const char * stdname
;
1035 const char * dstname
;
1039 int_fast32_t stdoffset
;
1040 int_fast32_t dstoffset
;
1044 dstname
= NULL
; /* XXX gcc */
1047 stdlen
= sizeof gmt
- 1;
1054 name
= getqzname(name
, '>');
1057 stdlen
= name
- stdname
;
1060 name
= getzname(name
);
1061 stdlen
= name
- stdname
;
1065 name
= getoffset(name
, &stdoffset
);
1069 charcnt
= stdlen
+ 1;
1070 if (sizeof sp
->chars
< charcnt
)
1072 load_ok
= tzload(TZDEFRULES
, sp
, false) == 0;
1074 sp
->leapcnt
= 0; /* so, we're off a little */
1075 if (*name
!= '\0') {
1078 name
= getqzname(name
, '>');
1081 dstlen
= name
- dstname
;
1085 name
= getzname(name
);
1086 dstlen
= name
- dstname
; /* length of DST zone name */
1090 charcnt
+= dstlen
+ 1;
1091 if (sizeof sp
->chars
< charcnt
)
1093 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1094 name
= getoffset(name
, &dstoffset
);
1097 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1098 if (*name
== '\0' && !load_ok
)
1099 name
= TZDEFRULESTRING
;
1100 if (*name
== ',' || *name
== ';') {
1109 if ((name
= getrule(name
, &start
)) == NULL
)
1113 if ((name
= getrule(name
, &end
)) == NULL
)
1117 sp
->typecnt
= 2; /* standard time and DST */
1119 ** Two transitions per year, from EPOCH_YEAR forward.
1121 init_ttinfo(&sp
->ttis
[0], -dstoffset
, true,
1123 init_ttinfo(&sp
->ttis
[1], -stdoffset
, false, 0);
1124 sp
->defaulttype
= 0;
1127 yearlim
= EPOCH_YEAR
+ YEARSPERREPEAT
;
1128 for (year
= EPOCH_YEAR
; year
< yearlim
; year
++) {
1130 starttime
= transtime(year
, &start
, stdoffset
),
1131 endtime
= transtime(year
, &end
, dstoffset
);
1133 yearsecs
= (year_lengths
[isleap(year
)]
1135 bool reversed
= endtime
< starttime
;
1137 int_fast32_t swap
= starttime
;
1138 starttime
= endtime
;
1142 || (starttime
< endtime
1143 && (endtime
- starttime
1145 + (stdoffset
- dstoffset
))))) {
1146 if (TZ_MAX_TIMES
- 2 < timecnt
)
1148 yearlim
= year
+ YEARSPERREPEAT
+ 1;
1149 sp
->ats
[timecnt
] = janfirst
;
1150 if (increment_overflow_time
1151 (&sp
->ats
[timecnt
], starttime
))
1153 sp
->types
[timecnt
++] = reversed
;
1154 sp
->ats
[timecnt
] = janfirst
;
1155 if (increment_overflow_time
1156 (&sp
->ats
[timecnt
], endtime
))
1158 sp
->types
[timecnt
++] = !reversed
;
1160 if (increment_overflow_time(&janfirst
, yearsecs
))
1163 sp
->timecnt
= timecnt
;
1165 sp
->typecnt
= 1; /* Perpetual DST. */
1167 int_fast32_t theirstdoffset
;
1168 int_fast32_t theirdstoffset
;
1169 int_fast32_t theiroffset
;
1177 ** Initial values of theirstdoffset and theirdstoffset.
1180 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1182 if (!sp
->ttis
[j
].tt_isdst
) {
1184 -sp
->ttis
[j
].tt_gmtoff
;
1189 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1191 if (sp
->ttis
[j
].tt_isdst
) {
1193 -sp
->ttis
[j
].tt_gmtoff
;
1198 ** Initially we're assumed to be in standard time.
1201 theiroffset
= theirstdoffset
;
1203 ** Now juggle transition times and types
1204 ** tracking offsets as you do.
1206 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1208 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1209 if (sp
->ttis
[j
].tt_ttisgmt
) {
1210 /* No adjustment to transition time */
1213 ** If summer time is in effect, and the
1214 ** transition time was not specified as
1215 ** standard time, add the summer time
1216 ** offset to the transition time;
1217 ** otherwise, add the standard time
1218 ** offset to the transition time.
1221 ** Transitions from DST to DDST
1222 ** will effectively disappear since
1223 ** POSIX provides for only one DST
1226 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1227 sp
->ats
[i
] += (time_t)
1228 (dstoffset
- theirdstoffset
);
1230 sp
->ats
[i
] += (time_t)
1231 (stdoffset
- theirstdoffset
);
1234 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1235 if (sp
->ttis
[j
].tt_isdst
)
1236 theirstdoffset
= theiroffset
;
1237 else theirdstoffset
= theiroffset
;
1240 ** Finally, fill in ttis.
1242 init_ttinfo(&sp
->ttis
[0], -stdoffset
, false, 0);
1243 init_ttinfo(&sp
->ttis
[1], -dstoffset
, true,
1246 sp
->defaulttype
= 0;
1250 sp
->typecnt
= 1; /* only standard time */
1252 init_ttinfo(&sp
->ttis
[0], -stdoffset
, false, 0);
1253 init_ttinfo(&sp
->ttis
[1], 0, false, 0);
1254 sp
->defaulttype
= 0;
1256 sp
->charcnt
= charcnt
;
1258 (void) memcpy(cp
, stdname
, stdlen
);
1262 (void) memcpy(cp
, dstname
, dstlen
);
1263 *(cp
+ dstlen
) = '\0';
1269 gmtload(struct state
*const sp
)
1271 if (tzload(gmt
, sp
, true) != 0)
1272 (void) tzparse(gmt
, sp
, true);
1276 zoneinit(struct state
*sp
, char const *name
)
1278 if (name
&& ! name
[0]) {
1280 ** User wants it fast rather than right.
1282 sp
->leapcnt
= 0; /* so, we're off a little */
1286 sp
->goback
= sp
->goahead
= false;
1287 init_ttinfo(&sp
->ttis
[0], 0, false, 0);
1288 strcpy(sp
->chars
, gmt
);
1289 sp
->defaulttype
= 0;
1292 int err
= tzload(name
, sp
, true);
1293 if (err
!= 0 && name
&& name
[0] != ':' &&
1294 tzparse(name
, sp
, false))
1303 tzsetlcl(char const *name
)
1305 struct state
*sp
= lclptr
;
1306 int lcl
= name
? strlen(name
) < sizeof lcl_TZname
: -1;
1307 if (lcl
< 0 ? lcl_is_set
< 0
1308 : 0 < lcl_is_set
&& strcmp(lcl_TZname
, name
) == 0)
1312 lclptr
= sp
= malloc(sizeof *lclptr
);
1314 if (zoneinit(sp
, name
) != 0)
1317 strcpy(lcl_TZname
, name
);
1327 rwlock_wrlock(&lcl_lock
);
1329 rwlock_unlock(&lcl_lock
);
1334 tzset_unlocked(void)
1336 tzsetlcl(getenv("TZ"));
1342 rwlock_wrlock(&lcl_lock
);
1344 rwlock_unlock(&lcl_lock
);
1350 static bool gmt_is_set
;
1351 rwlock_wrlock(&lcl_lock
);
1353 gmtptr
= malloc(sizeof *gmtptr
);
1358 rwlock_unlock(&lcl_lock
);
1364 tzalloc(const char *name
)
1366 timezone_t sp
= malloc(sizeof *sp
);
1368 int err
= zoneinit(sp
, name
);
1379 tzfree(timezone_t sp
)
1385 ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1386 ** ctime_r are obsolescent and have potential security problems that
1387 ** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1389 ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1390 ** in zones with three or more time zone abbreviations.
1391 ** Callers can instead use localtime_rz + strftime.
1397 ** The easy way to behave "as if no library function calls" localtime
1398 ** is to not call it, so we drop its guts into "localsub", which can be
1399 ** freely called. (And no, the PANS doesn't require the above behavior,
1400 ** but it *is* desirable.)
1402 ** If successful and SETNAME is nonzero,
1403 ** set the applicable parts of tzname, timezone and altzone;
1404 ** however, it's OK to omit this step if the time zone is POSIX-compatible,
1405 ** since in that case tzset should have already done this step correctly.
1406 ** SETNAME's type is intfast32_t for compatibility with gmtsub,
1407 ** but it is actually a boolean and its value should be 0 or 1.
1412 localsub(struct state
const *sp
, time_t const *timep
, int_fast32_t setname
,
1413 struct tm
*const tmp
)
1415 const struct ttinfo
* ttisp
;
1418 const time_t t
= *timep
;
1421 /* Don't bother to set tzname etc.; tzset has already done it. */
1422 return gmtsub(gmtptr
, timep
, 0, tmp
);
1424 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1425 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1431 seconds
= sp
->ats
[0] - t
;
1432 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1434 years
= (time_t)((seconds
/ SECSPERREPEAT
+ 1) * YEARSPERREPEAT
);
1435 seconds
= (time_t)(years
* AVGSECSPERYEAR
);
1438 else newt
-= seconds
;
1439 if (newt
< sp
->ats
[0] ||
1440 newt
> sp
->ats
[sp
->timecnt
- 1]) {
1442 return NULL
; /* "cannot happen" */
1444 result
= localsub(sp
, &newt
, setname
, tmp
);
1448 newy
= result
->tm_year
;
1452 if (! (INT_MIN
<= newy
&& newy
<= INT_MAX
)) {
1456 result
->tm_year
= (int)newy
;
1460 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1461 i
= sp
->defaulttype
;
1464 int hi
= sp
->timecnt
;
1467 int mid
= (lo
+ hi
) / 2;
1469 if (t
< sp
->ats
[mid
])
1473 i
= (int) sp
->types
[lo
- 1];
1475 ttisp
= &sp
->ttis
[i
];
1477 ** To get (wrong) behavior that's compatible with System V Release 2.0
1478 ** you'd replace the statement below with
1479 ** t += ttisp->tt_gmtoff;
1480 ** timesub(&t, 0L, sp, tmp);
1482 result
= timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1484 result
->tm_isdst
= ttisp
->tt_isdst
;
1486 result
->TM_ZONE
= __UNCONST(&sp
->chars
[ttisp
->tt_abbrind
]);
1487 #endif /* defined TM_ZONE */
1489 update_tzname_etc(sp
, ttisp
);
1497 localtime_rz(timezone_t sp
, time_t const *timep
, struct tm
*tmp
)
1499 return localsub(sp
, timep
, 0, tmp
);
1505 localtime_tzset(time_t const *timep
, struct tm
*tmp
, bool setname
)
1507 rwlock_wrlock(&lcl_lock
);
1508 if (setname
|| !lcl_is_set
)
1510 tmp
= localsub(lclptr
, timep
, setname
, tmp
);
1511 rwlock_unlock(&lcl_lock
);
1516 localtime(const time_t *timep
)
1518 return localtime_tzset(timep
, &tm
, true);
1522 localtime_r(const time_t * __restrict timep
, struct tm
*tmp
)
1524 return localtime_tzset(timep
, tmp
, false);
1528 ** gmtsub is to gmtime as localsub is to localtime.
1532 gmtsub(struct state
const *sp
, const time_t *timep
, int_fast32_t offset
,
1537 result
= timesub(timep
, offset
, gmtptr
, tmp
);
1540 ** Could get fancy here and deliver something such as
1541 ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
1542 ** but this is no time for a treasure hunt.
1545 result
->TM_ZONE
= offset
? __UNCONST(wildabbr
) : gmtptr
?
1546 gmtptr
->chars
: __UNCONST(gmt
);
1547 #endif /* defined TM_ZONE */
1553 ** Re-entrant version of gmtime.
1557 gmtime_r(const time_t *timep
, struct tm
*tmp
)
1560 return gmtsub(NULL
, timep
, 0, tmp
);
1564 gmtime(const time_t *timep
)
1566 return gmtime_r(timep
, &tm
);
1571 offtime(const time_t *timep
, long offset
)
1574 return gmtsub(gmtptr
, timep
, (int_fast32_t)offset
, &tm
);
1578 offtime_r(const time_t *timep
, long offset
, struct tm
*tmp
)
1581 return gmtsub(NULL
, timep
, (int_fast32_t)offset
, tmp
);
1584 #endif /* defined STD_INSPIRED */
1587 ** Return the number of leap years through the end of the given year
1588 ** where, to make the math easy, the answer for year zero is defined as zero.
1591 static int ATTRIBUTE_PURE
1592 leaps_thru_end_of(const int y
)
1594 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1595 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1599 timesub(const time_t *timep
, int_fast32_t offset
,
1600 const struct state
*sp
, struct tm
*tmp
)
1602 const struct lsinfo
* lp
;
1604 int idays
; /* unsigned would be so 2003 */
1614 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1617 if (*timep
>= lp
->ls_trans
) {
1618 if (*timep
== lp
->ls_trans
) {
1619 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1620 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1623 sp
->lsis
[i
].ls_trans
==
1624 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1625 sp
->lsis
[i
].ls_corr
==
1626 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1636 tdays
= (time_t)(*timep
/ SECSPERDAY
);
1637 rem
= *timep
% SECSPERDAY
;
1638 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1644 tdelta
= tdays
/ DAYSPERLYEAR
;
1645 if (! ((! TYPE_SIGNED(time_t) || INT_MIN
<= tdelta
)
1646 && tdelta
<= INT_MAX
))
1648 _DIAGASSERT(__type_fit(int, tdelta
));
1649 idelta
= (int)tdelta
;
1651 idelta
= (tdays
< 0) ? -1 : 1;
1653 if (increment_overflow(&newy
, idelta
))
1655 leapdays
= leaps_thru_end_of(newy
- 1) -
1656 leaps_thru_end_of(y
- 1);
1657 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
1662 ** Given the range, we can now fearlessly cast...
1664 idays
= (int) tdays
;
1665 rem
+= offset
- corr
;
1670 while (rem
>= SECSPERDAY
) {
1675 if (increment_overflow(&y
, -1))
1677 idays
+= year_lengths
[isleap(y
)];
1679 while (idays
>= year_lengths
[isleap(y
)]) {
1680 idays
-= year_lengths
[isleap(y
)];
1681 if (increment_overflow(&y
, 1))
1685 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1687 tmp
->tm_yday
= idays
;
1689 ** The "extra" mods below avoid overflow problems.
1691 tmp
->tm_wday
= EPOCH_WDAY
+
1692 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
1693 (DAYSPERNYEAR
% DAYSPERWEEK
) +
1694 leaps_thru_end_of(y
- 1) -
1695 leaps_thru_end_of(EPOCH_YEAR
- 1) +
1697 tmp
->tm_wday
%= DAYSPERWEEK
;
1698 if (tmp
->tm_wday
< 0)
1699 tmp
->tm_wday
+= DAYSPERWEEK
;
1700 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1702 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1704 ** A positive leap second requires a special
1705 ** representation. This uses "... ??:59:60" et seq.
1707 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1708 ip
= mon_lengths
[isleap(y
)];
1709 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1710 idays
-= ip
[tmp
->tm_mon
];
1711 tmp
->tm_mday
= (int) (idays
+ 1);
1714 tmp
->TM_GMTOFF
= offset
;
1715 #endif /* defined TM_GMTOFF */
1722 #if !defined(__minix) || !defined(_LIBMINC)
1724 ctime(const time_t *timep
)
1727 ** Section 4.12.3.2 of X3.159-1989 requires that
1728 ** The ctime function converts the calendar time pointed to by timer
1729 ** to local time in the form of a string. It is equivalent to
1730 ** asctime(localtime(timer))
1732 struct tm
*tmp
= localtime(timep
);
1733 return tmp
? asctime(tmp
) : NULL
;
1737 ctime_r(const time_t *timep
, char *buf
)
1740 struct tm
*tmp
= localtime_r(timep
, &mytm
);
1741 return tmp
? asctime_r(tmp
, buf
) : NULL
;
1745 ctime_rz(const timezone_t sp
, const time_t * timep
, char *buf
)
1747 struct tm mytm
, *rtm
;
1749 rtm
= localtime_rz(sp
, timep
, &mytm
);
1752 return asctime_r(rtm
, buf
);
1754 #endif /* !defined(__minix) || !defined(_LIBMINC) */
1757 ** Adapted from code provided by Robert Elz, who writes:
1758 ** The "best" way to do mktime I think is based on an idea of Bob
1759 ** Kridle's (so its said...) from a long time ago.
1760 ** It does a binary search of the time_t space. Since time_t's are
1761 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1762 ** would still be very reasonable).
1766 #define WRONG ((time_t)-1)
1767 #endif /* !defined WRONG */
1770 ** Normalize logic courtesy Paul Eggert.
1774 increment_overflow(int *ip
, int j
)
1779 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1780 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1781 ** If i < 0 there can only be overflow if i + j < INT_MIN
1782 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1784 if ((i
>= 0) ? (j
> INT_MAX
- i
) : (j
< INT_MIN
- i
))
1791 increment_overflow32(int_fast32_t *const lp
, int const m
)
1793 int_fast32_t const l
= *lp
;
1795 if ((l
>= 0) ? (m
> INT_FAST32_MAX
- l
) : (m
< INT_FAST32_MIN
- l
))
1802 increment_overflow_time(time_t *tp
, int_fast32_t j
)
1806 ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
1807 ** except that it does the right thing even if *tp + j would overflow.
1810 ? (TYPE_SIGNED(time_t) ? time_t_min
- j
<= *tp
: -1 - j
< *tp
)
1811 : *tp
<= time_t_max
- j
))
1818 normalize_overflow(int *const tensptr
, int *const unitsptr
, const int base
)
1822 tensdelta
= (*unitsptr
>= 0) ?
1823 (*unitsptr
/ base
) :
1824 (-1 - (-1 - *unitsptr
) / base
);
1825 *unitsptr
-= tensdelta
* base
;
1826 return increment_overflow(tensptr
, tensdelta
);
1830 normalize_overflow32(int_fast32_t *tensptr
, int *unitsptr
, int base
)
1834 tensdelta
= (*unitsptr
>= 0) ?
1835 (*unitsptr
/ base
) :
1836 (-1 - (-1 - *unitsptr
) / base
);
1837 *unitsptr
-= tensdelta
* base
;
1838 return increment_overflow32(tensptr
, tensdelta
);
1842 tmcomp(const struct tm
*const atmp
,
1843 const struct tm
*const btmp
)
1847 if (atmp
->tm_year
!= btmp
->tm_year
)
1848 return atmp
->tm_year
< btmp
->tm_year
? -1 : 1;
1849 if ((result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1850 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1851 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1852 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1853 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1858 time2sub(struct tm
*const tmp
,
1859 struct tm
*(*funcp
)(struct state
const *, time_t const *,
1860 int_fast32_t, struct tm
*),
1861 struct state
const *sp
,
1862 const int_fast32_t offset
,
1872 #ifdef NO_ERROR_IN_DST_GAP
1878 struct tm yourtm
, mytm
;
1882 #ifdef NO_ERROR_IN_DST_GAP
1886 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1890 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1892 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1895 if (normalize_overflow32(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1898 ** Turn y into an actual year number for now.
1899 ** It is converted back to an offset from TM_YEAR_BASE later.
1901 if (increment_overflow32(&y
, TM_YEAR_BASE
))
1903 while (yourtm
.tm_mday
<= 0) {
1904 if (increment_overflow32(&y
, -1))
1906 li
= y
+ (1 < yourtm
.tm_mon
);
1907 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1909 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1910 li
= y
+ (1 < yourtm
.tm_mon
);
1911 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1912 if (increment_overflow32(&y
, 1))
1916 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1917 if (yourtm
.tm_mday
<= i
)
1919 yourtm
.tm_mday
-= i
;
1920 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1922 if (increment_overflow32(&y
, 1))
1926 if (increment_overflow32(&y
, -TM_YEAR_BASE
))
1928 if (! (INT_MIN
<= y
&& y
<= INT_MAX
))
1930 yourtm
.tm_year
= (int)y
;
1931 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1933 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1935 ** We can't set tm_sec to 0, because that might push the
1936 ** time below the minimum representable time.
1937 ** Set tm_sec to 59 instead.
1938 ** This assumes that the minimum representable time is
1939 ** not in the same minute that a leap second was deleted from,
1940 ** which is a safer assumption than using 58 would be.
1942 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1944 saved_seconds
= yourtm
.tm_sec
;
1945 yourtm
.tm_sec
= SECSPERMIN
- 1;
1947 saved_seconds
= yourtm
.tm_sec
;
1951 ** Do a binary search (this works whatever time_t's type is).
1955 #ifdef NO_ERROR_IN_DST_GAP
1959 t
= lo
/ 2 + hi
/ 2;
1964 if (! funcp(sp
, &t
, offset
, &mytm
)) {
1966 ** Assume that t is too extreme to be represented in
1967 ** a struct tm; arrange things so that it is less
1968 ** extreme on the next pass.
1970 dir
= (t
> 0) ? 1 : -1;
1971 } else dir
= tmcomp(&mytm
, &yourtm
);
1974 if (t
== time_t_max
)
1978 } else if (t
== hi
) {
1979 if (t
== time_t_min
)
1984 #ifdef NO_ERROR_IN_DST_GAP
1985 if (ilo
!= lo
&& lo
- 1 == hi
&& yourtm
.tm_isdst
< 0 &&
1987 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1988 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1990 if (sp
->ttis
[j
].tt_isdst
==
1991 sp
->ttis
[i
].tt_isdst
)
1993 off
= sp
->ttis
[j
].tt_gmtoff
-
1994 sp
->ttis
[i
].tt_gmtoff
;
1995 yourtm
.tm_sec
+= off
< 0 ?
2009 #if defined TM_GMTOFF && ! UNINIT_TRAP
2010 if (mytm
.TM_GMTOFF
!= yourtm
.TM_GMTOFF
2011 && (yourtm
.TM_GMTOFF
< 0
2012 ? (-SECSPERDAY
<= yourtm
.TM_GMTOFF
2013 && (mytm
.TM_GMTOFF
<=
2014 (/*CONSTCOND*/SMALLEST (INT_FAST32_MAX
, LONG_MAX
)
2015 + yourtm
.TM_GMTOFF
)))
2016 : (yourtm
.TM_GMTOFF
<= SECSPERDAY
2017 && ((/*CONSTCOND*/BIGGEST (INT_FAST32_MIN
, LONG_MIN
)
2019 <= mytm
.TM_GMTOFF
)))) {
2020 /* MYTM matches YOURTM except with the wrong UTC offset.
2021 YOURTM.TM_GMTOFF is plausible, so try it instead.
2022 It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2023 since the guess gets checked. */
2025 int_fast32_t diff
= (int_fast32_t)
2026 (mytm
.TM_GMTOFF
- yourtm
.TM_GMTOFF
);
2027 if (!increment_overflow_time(&altt
, diff
)) {
2029 if (! funcp(sp
, &altt
, offset
, &alttm
)
2030 && alttm
.tm_isdst
== mytm
.tm_isdst
2031 && alttm
.TM_GMTOFF
== yourtm
.TM_GMTOFF
2032 && tmcomp(&alttm
, &yourtm
)) {
2039 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
2042 ** Right time, wrong type.
2043 ** Hunt for right time, right type.
2044 ** It's okay to guess wrong since the guess
2049 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
2050 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
2052 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
2053 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
2055 newt
= (time_t)(t
+ sp
->ttis
[j
].tt_gmtoff
-
2056 sp
->ttis
[i
].tt_gmtoff
);
2057 if (! funcp(sp
, &newt
, offset
, &mytm
))
2059 if (tmcomp(&mytm
, &yourtm
) != 0)
2061 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
2073 newt
= t
+ saved_seconds
;
2074 if ((newt
< t
) != (saved_seconds
< 0))
2077 if (funcp(sp
, &t
, offset
, tmp
)) {
2090 time2(struct tm
* const tmp
,
2091 struct tm
*(*funcp
)(struct state
const *, time_t const *,
2092 int_fast32_t, struct tm
*),
2093 struct state
const *sp
,
2094 const int_fast32_t offset
,
2100 ** First try without normalization of seconds
2101 ** (in case tm_sec contains a value associated with a leap second).
2102 ** If that fails, try with normalization of seconds.
2104 t
= time2sub(tmp
, funcp
, sp
, offset
, okayp
, false);
2105 return *okayp
? t
: time2sub(tmp
, funcp
, sp
, offset
, okayp
, true);
2109 time1(struct tm
*const tmp
,
2110 struct tm
*(*funcp
) (struct state
const *, time_t const *,
2111 int_fast32_t, struct tm
*),
2112 struct state
const *sp
,
2113 const int_fast32_t offset
)
2117 int sameind
, otherind
;
2121 char seen
[TZ_MAX_TYPES
];
2122 unsigned char types
[TZ_MAX_TYPES
];
2129 if (tmp
->tm_isdst
> 1)
2132 t
= time2(tmp
, funcp
, sp
, offset
, &okay
);
2137 if (tmp
->tm_isdst
< 0)
2140 ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2142 tmp
->tm_isdst
= 0; /* reset to std and try again */
2145 #endif /* !defined PCTS */
2147 ** We're supposed to assume that somebody took a time of one type
2148 ** and did some math on it that yielded a "struct tm" that's bad.
2149 ** We try to divine the type they started from and adjust to the
2156 for (i
= 0; i
< sp
->typecnt
; ++i
)
2159 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
2160 if (!seen
[sp
->types
[i
]]) {
2161 seen
[sp
->types
[i
]] = true;
2162 types
[nseen
++] = sp
->types
[i
];
2164 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2165 samei
= types
[sameind
];
2166 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2168 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2169 otheri
= types
[otherind
];
2170 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
2172 tmp
->tm_sec
+= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2173 sp
->ttis
[samei
].tt_gmtoff
);
2174 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2175 t
= time2(tmp
, funcp
, sp
, offset
, &okay
);
2180 tmp
->tm_sec
-= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2181 sp
->ttis
[samei
].tt_gmtoff
);
2182 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2190 mktime_tzname(timezone_t sp
, struct tm
*tmp
, bool setname
)
2193 return time1(tmp
, localsub
, sp
, setname
);
2196 return time1(tmp
, gmtsub
, gmtptr
, 0);
2203 mktime_z(timezone_t sp
, struct tm
*const tmp
)
2205 return mktime_tzname(sp
, tmp
, false);
2211 mktime(struct tm
*tmp
)
2215 rwlock_wrlock(&lcl_lock
);
2217 t
= mktime_tzname(lclptr
, tmp
, true);
2218 rwlock_unlock(&lcl_lock
);
2225 timelocal_z(const timezone_t sp
, struct tm
*const tmp
)
2228 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2229 return mktime_z(sp
, tmp
);
2233 timelocal(struct tm
*tmp
)
2236 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2241 timegm(struct tm
*tmp
)
2244 return timeoff(tmp
, 0);
2248 timeoff(struct tm
*tmp
, long offset
)
2253 return time1(tmp
, gmtsub
, gmtptr
, (int_fast32_t)offset
);
2256 #endif /* defined STD_INSPIRED */
2259 ** XXX--is the below the right way to conditionalize??
2265 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2266 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2267 ** is not the case if we are accounting for leap seconds.
2268 ** So, we provide the following conversion routines for use
2269 ** when exchanging timestamps with POSIX conforming systems.
2273 leapcorr(const timezone_t sp
, time_t t
)
2275 struct lsinfo
const * lp
;
2281 if (t
>= lp
->ls_trans
)
2287 NETBSD_INSPIRED_EXTERN
time_t ATTRIBUTE_PURE
2288 time2posix_z(timezone_t sp
, time_t t
)
2290 return (time_t)(t
- leapcorr(sp
, t
));
2294 time2posix(time_t t
)
2296 rwlock_wrlock(&lcl_lock
);
2300 t
= (time_t)(t
- leapcorr(lclptr
, t
));
2301 rwlock_unlock(&lcl_lock
);
2305 NETBSD_INSPIRED_EXTERN
time_t ATTRIBUTE_PURE
2306 posix2time_z(timezone_t sp
, time_t t
)
2312 ** For a positive leap second hit, the result
2313 ** is not unique. For a negative leap second
2314 ** hit, the corresponding time doesn't exist,
2315 ** so we return an adjacent second.
2317 x
= (time_t)(t
+ leapcorr(sp
, t
));
2318 y
= (time_t)(x
- leapcorr(sp
, x
));
2322 y
= (time_t)(x
- leapcorr(sp
, x
));
2328 y
= (time_t)(x
- leapcorr(sp
, x
));
2336 posix2time(time_t t
)
2338 rwlock_wrlock(&lcl_lock
);
2342 t
= posix2time_z(lclptr
, t
);
2343 rwlock_unlock(&lcl_lock
);
2347 #endif /* defined STD_INSPIRED */