1 /* $NetBSD: localtime.c,v 1.78 2013/09/20 19:06:54 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.78 2013/09/20 19:06:54 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"
29 #include "reentrant.h"
31 #if defined(__weak_alias)
32 __weak_alias(daylight
,_daylight
)
33 __weak_alias(tzname
,_tzname
)
36 #ifndef TZ_ABBR_MAX_LEN
37 #define TZ_ABBR_MAX_LEN 16
38 #endif /* !defined TZ_ABBR_MAX_LEN */
40 #ifndef TZ_ABBR_CHAR_SET
41 #define TZ_ABBR_CHAR_SET \
42 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
43 #endif /* !defined TZ_ABBR_CHAR_SET */
45 #ifndef TZ_ABBR_ERR_CHAR
46 #define TZ_ABBR_ERR_CHAR '_'
47 #endif /* !defined TZ_ABBR_ERR_CHAR */
50 ** SunOS 4.1.1 headers lack O_BINARY.
54 #define OPEN_MODE (O_RDONLY | O_BINARY)
55 #endif /* defined O_BINARY */
57 #define OPEN_MODE O_RDONLY
58 #endif /* !defined O_BINARY */
62 ** Someone might make incorrect use of a time zone abbreviation:
63 ** 1. They might reference tzname[0] before calling tzset (explicitly
65 ** 2. They might reference tzname[1] before calling tzset (explicitly
67 ** 3. They might reference tzname[1] after setting to a time zone
68 ** in which Daylight Saving Time is never observed.
69 ** 4. They might reference tzname[0] after setting to a time zone
70 ** in which Standard Time is never observed.
71 ** 5. They might reference tm.TM_ZONE after calling offtime.
72 ** What's best to do in the above cases is open to debate;
73 ** for now, we just set things up so that in any of the five cases
74 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
75 ** string "tzname[0] used before set", and similarly for the other cases.
76 ** And another: initialize tzname[0] to "ERA", with an explanation in the
77 ** manual page of what this "time zone abbreviation" means (doing this so
78 ** that tzname[0] has the "normal" length of three characters).
81 #endif /* !defined WILDABBR */
83 static const char wildabbr
[] = WILDABBR
;
85 static const char gmt
[] = "GMT";
88 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
89 ** We default to US rules as of 1999-08-17.
90 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
91 ** implementation dependent; for historical reasons, US rules are a
94 #ifndef TZDEFRULESTRING
95 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
96 #endif /* !defined TZDEFDST */
98 struct ttinfo
{ /* time type information */
99 int_fast32_t tt_gmtoff
; /* UT offset in seconds */
100 int tt_isdst
; /* used to set tm_isdst */
101 int tt_abbrind
; /* abbreviation list index */
102 int tt_ttisstd
; /* TRUE if transition is std time */
103 int tt_ttisgmt
; /* TRUE if transition is UT */
106 struct lsinfo
{ /* leap second information */
107 time_t ls_trans
; /* transition time */
108 int_fast64_t ls_corr
; /* correction to apply */
111 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
114 #define MY_TZNAME_MAX TZNAME_MAX
115 #endif /* defined TZNAME_MAX */
117 #define MY_TZNAME_MAX 255
118 #endif /* !defined TZNAME_MAX */
127 time_t ats
[TZ_MAX_TIMES
];
128 unsigned char types
[TZ_MAX_TIMES
];
129 struct ttinfo ttis
[TZ_MAX_TYPES
];
130 char chars
[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1,
131 sizeof gmt
), (2 * (MY_TZNAME_MAX
+ 1)))];
132 struct lsinfo lsis
[TZ_MAX_LEAPS
];
133 int defaulttype
; /* for early times or if no transitions */
137 int r_type
; /* type of rule--see below */
138 int r_day
; /* day number of rule */
139 int r_week
; /* week number of rule */
140 int r_mon
; /* month number of rule */
141 int_fast32_t r_time
; /* transition time of rule */
144 #define JULIAN_DAY 0 /* Jn - Julian day */
145 #define DAY_OF_YEAR 1 /* n - day of year */
146 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
148 typedef struct tm
*(*subfun_t
)(const timezone_t sp
, const time_t *timep
,
149 const int_fast32_t offset
, struct tm
*tmp
);
152 ** Prototypes for static functions.
155 static int_fast32_t detzcode(const char * codep
);
156 static time_t detzcode64(const char * codep
);
157 static int differ_by_repeat(time_t t1
, time_t t0
);
158 static const char * getzname(const char * strp
) ATTRIBUTE_PURE
;
159 static const char * getqzname(const char * strp
, const int delim
) ATTRIBUTE_PURE
;
160 static const char * getnum(const char * strp
, int * nump
, int min
,
162 static const char * getsecs(const char * strp
, int_fast32_t * secsp
);
163 static const char * getoffset(const char * strp
, int_fast32_t * offsetp
);
164 static const char * getrule(const char * strp
, struct rule
* rulep
);
165 static void gmtload(timezone_t sp
);
166 static struct tm
* gmtsub(const timezone_t sp
, const time_t *timep
,
167 const int_fast32_t offset
, struct tm
* tmp
);
168 static struct tm
* localsub(const timezone_t sp
, const time_t *timep
,
169 const int_fast32_t offset
, struct tm
*tmp
);
170 static int increment_overflow(int * number
, int delta
);
171 static int increment_overflow32(int_fast32_t * number
, int delta
);
172 static int leaps_thru_end_of(int y
) ATTRIBUTE_PURE
;
173 static int normalize_overflow(int * tensptr
, int * unitsptr
,
175 static int normalize_overflow32(int_fast32_t * tensptr
,
176 int * unitsptr
, int base
);
177 static void settzname(void);
178 static time_t time1(const timezone_t sp
, struct tm
* const tmp
,
179 subfun_t funcp
, const int_fast32_t offset
);
180 static time_t time2(const timezone_t sp
, struct tm
* const tmp
,
182 const int_fast32_t offset
, int *const okayp
);
183 static time_t time2sub(const timezone_t sp
, struct tm
* const tmp
,
184 subfun_t funcp
, const int_fast32_t offset
,
185 int *const okayp
, const int do_norm_secs
);
186 static struct tm
* timesub(const timezone_t sp
, const time_t * timep
,
187 const int_fast32_t offset
, struct tm
* tmp
);
188 static int tmcomp(const struct tm
* atmp
,
189 const struct tm
* btmp
);
190 static time_t transtime(time_t janfirst
, int year
,
191 const struct rule
* rulep
,
192 const int_fast32_t offset
) ATTRIBUTE_PURE
;
193 static int typesequiv(const timezone_t sp
, int a
, int b
);
194 static int tzload(timezone_t sp
, const char * name
,
196 static int tzparse(timezone_t sp
, const char * name
,
198 static void tzset_unlocked(void);
199 static void tzsetwall_unlocked(void);
200 static int_fast64_t leapcorr(const timezone_t sp
, time_t * timep
);
202 static timezone_t lclptr
;
203 static timezone_t gmtptr
;
205 #ifndef TZ_STRLEN_MAX
206 #define TZ_STRLEN_MAX 255
207 #endif /* !defined TZ_STRLEN_MAX */
209 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
210 static int lcl_is_set
;
211 static int gmt_is_set
;
213 #if !defined(__LIBC12_SOURCE__)
215 __aconst
char * tzname
[2] = {
216 (__aconst
char *)__UNCONST(wildabbr
),
217 (__aconst
char *)__UNCONST(wildabbr
)
222 extern __aconst
char * tzname
[2];
227 static rwlock_t lcl_lock
= RWLOCK_INITIALIZER
;
231 ** Section 4.12.3 of X3.159-1989 requires that
232 ** Except for the strftime function, these functions [asctime,
233 ** ctime, gmtime, localtime] return values in one of two static
234 ** objects: a broken-down time structure and an array of char.
235 ** Thanks to Paul Eggert for noting this.
241 #if !defined(__LIBC12_SOURCE__)
246 extern long timezone
__RENAME(__timezone13
);
248 #endif /* defined USG_COMPAT */
252 #endif /* defined ALTZONE */
255 detzcode(const char *const codep
)
260 result
= (codep
[0] & 0x80) ? -1 : 0;
261 for (i
= 0; i
< 4; ++i
)
262 result
= (result
<< 8) | (codep
[i
] & 0xff);
267 detzcode64(const char *const codep
)
272 result
= (time_t)((codep
[0] & 0x80) ? (~(int_fast64_t) 0) : 0);
273 for (i
= 0; i
< 8; ++i
)
274 result
= result
* 256 + (codep
[i
] & 0xff);
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
];
292 settzname_z(timezone_t sp
)
297 ** Scrub the abbreviations.
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';
319 timezone_t
const sp
= lclptr
;
322 tzname
[0] = (__aconst
char *)__UNCONST(wildabbr
);
323 tzname
[1] = (__aconst
char *)__UNCONST(wildabbr
);
327 #endif /* defined USG_COMPAT */
330 #endif /* defined ALTZONE */
332 tzname
[0] = tzname
[1] = (__aconst
char *)__UNCONST(gmt
);
336 ** And to get the latest zone names into tzname. . .
338 for (i
= 0; i
< sp
->typecnt
; ++i
) {
339 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
341 tzname
[ttisp
->tt_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
345 if (!ttisp
->tt_isdst
)
346 timezone
= -(ttisp
->tt_gmtoff
);
347 #endif /* defined USG_COMPAT */
350 altzone
= -(ttisp
->tt_gmtoff
);
351 #endif /* defined ALTZONE */
357 differ_by_repeat(const time_t t1
, const time_t t0
)
359 if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
361 return (int_fast64_t)t1
- (int_fast64_t)t0
== SECSPERREPEAT
;
365 tzload(timezone_t sp
, const char *name
, const int doextend
)
373 struct tzhead tzhead
;
374 char buf
[2 * sizeof(struct tzhead
) +
380 up
= calloc(1, sizeof *up
);
384 sp
->goback
= sp
->goahead
= FALSE
;
385 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
390 ** Section 4.9.1 of the C standard says that
391 ** "FILENAME_MAX expands to an integral constant expression
392 ** that is the size needed for an array of char large enough
393 ** to hold the longest file name string that the implementation
394 ** guarantees can be opened."
396 char fullname
[FILENAME_MAX
+ 1];
400 doaccess
= name
[0] == '/';
402 if ((p
= TZDIR
) == NULL
)
404 if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
406 (void) strcpy(fullname
, p
); /* XXX strcpy is safe */
407 (void) strcat(fullname
, "/"); /* XXX strcat is safe */
408 (void) strcat(fullname
, name
); /* XXX strcat is safe */
410 ** Set doaccess if '.' (as in "../") shows up in name.
412 if (strchr(name
, '.') != NULL
)
416 if (doaccess
&& access(name
, R_OK
) != 0)
419 * XXX potential security problem here if user of a set-id
420 * program has set TZ (which is passed in as name) here,
421 * and uses a race condition trick to defeat the access(2)
424 if ((fid
= open(name
, OPEN_MODE
)) == -1)
427 nread
= read(fid
, up
->buf
, sizeof up
->buf
);
428 if (close(fid
) < 0 || nread
<= 0)
430 for (stored
= 4; stored
<= 8; stored
*= 2) {
434 ttisstdcnt
= (int) detzcode(up
->tzhead
.tzh_ttisstdcnt
);
435 ttisgmtcnt
= (int) detzcode(up
->tzhead
.tzh_ttisgmtcnt
);
436 sp
->leapcnt
= (int) detzcode(up
->tzhead
.tzh_leapcnt
);
437 sp
->timecnt
= (int) detzcode(up
->tzhead
.tzh_timecnt
);
438 sp
->typecnt
= (int) detzcode(up
->tzhead
.tzh_typecnt
);
439 sp
->charcnt
= (int) detzcode(up
->tzhead
.tzh_charcnt
);
440 p
= up
->tzhead
.tzh_charcnt
+ sizeof up
->tzhead
.tzh_charcnt
;
441 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
442 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
443 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
444 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
445 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
446 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
448 if (nread
- (p
- up
->buf
) <
449 sp
->timecnt
* stored
+ /* ats */
450 sp
->timecnt
+ /* types */
451 sp
->typecnt
* 6 + /* ttinfos */
452 sp
->charcnt
+ /* chars */
453 sp
->leapcnt
* (stored
+ 4) + /* lsinfos */
454 ttisstdcnt
+ /* ttisstds */
455 ttisgmtcnt
) /* ttisgmts */
457 for (i
= 0; i
< sp
->timecnt
; ++i
) {
458 sp
->ats
[i
] = (time_t)((stored
== 4) ?
459 detzcode(p
) : detzcode64(p
));
462 for (i
= 0; i
< sp
->timecnt
; ++i
) {
463 sp
->types
[i
] = (unsigned char) *p
++;
464 if (sp
->types
[i
] >= sp
->typecnt
)
467 for (i
= 0; i
< sp
->typecnt
; ++i
) {
468 struct ttinfo
* ttisp
;
470 ttisp
= &sp
->ttis
[i
];
471 ttisp
->tt_gmtoff
= detzcode(p
);
473 ttisp
->tt_isdst
= (unsigned char) *p
++;
474 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
476 ttisp
->tt_abbrind
= (unsigned char) *p
++;
477 if (ttisp
->tt_abbrind
< 0 ||
478 ttisp
->tt_abbrind
> sp
->charcnt
)
481 for (i
= 0; i
< sp
->charcnt
; ++i
)
483 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
484 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
485 struct lsinfo
* lsisp
;
487 lsisp
= &sp
->lsis
[i
];
488 lsisp
->ls_trans
= (time_t)((stored
== 4) ?
489 detzcode(p
) : detzcode64(p
));
491 lsisp
->ls_corr
= detzcode(p
);
494 for (i
= 0; i
< sp
->typecnt
; ++i
) {
495 struct ttinfo
* ttisp
;
497 ttisp
= &sp
->ttis
[i
];
499 ttisp
->tt_ttisstd
= FALSE
;
501 ttisp
->tt_ttisstd
= *p
++;
502 if (ttisp
->tt_ttisstd
!= TRUE
&&
503 ttisp
->tt_ttisstd
!= FALSE
)
507 for (i
= 0; i
< sp
->typecnt
; ++i
) {
508 struct ttinfo
* ttisp
;
510 ttisp
= &sp
->ttis
[i
];
512 ttisp
->tt_ttisgmt
= FALSE
;
514 ttisp
->tt_ttisgmt
= *p
++;
515 if (ttisp
->tt_ttisgmt
!= TRUE
&&
516 ttisp
->tt_ttisgmt
!= FALSE
)
521 ** Out-of-sort ats should mean we're running on a
522 ** signed time_t system but using a data file with
523 ** unsigned values (or vice versa).
525 for (i
= 0; i
< sp
->timecnt
; ++i
)
526 if ((i
< sp
->timecnt
- 1 &&
527 sp
->ats
[i
] > sp
->ats
[i
+ 1]) ||
528 (i
== sp
->timecnt
- 1 && !TYPE_SIGNED(time_t) &&
530 ((stored
== 4) ? INT32_MAX
: INT64_MAX
))) {
531 if (TYPE_SIGNED(time_t)) {
533 ** Ignore the end (easy).
538 ** Ignore the beginning (harder).
543 ** Keep the record right before the
545 ** but tweak it so that it starts
546 ** right with the epoch
547 ** (thanks to Doug Bailey).
550 for (j
= 0; j
+ i
< sp
->timecnt
; ++j
) {
551 sp
->ats
[j
] = sp
->ats
[j
+ i
];
552 sp
->types
[j
] = sp
->types
[j
+ i
];
559 ** If this is an old file, we're done.
561 if (up
->tzhead
.tzh_version
[0] == '\0')
563 nread
-= p
- up
->buf
;
564 for (i
= 0; i
< nread
; ++i
)
567 ** If this is a narrow time_t system, we're done.
569 if (stored
>= (int) sizeof(time_t))
572 if (doextend
&& nread
> 2 &&
573 up
->buf
[0] == '\n' && up
->buf
[nread
- 1] == '\n' &&
574 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
578 up
->buf
[nread
- 1] = '\0';
579 result
= tzparse(&ts
, &up
->buf
[1], FALSE
);
580 if (result
== 0 && ts
.typecnt
== 2 &&
581 sp
->charcnt
+ ts
.charcnt
<= TZ_MAX_CHARS
) {
582 for (i
= 0; i
< 2; ++i
)
583 ts
.ttis
[i
].tt_abbrind
+=
585 for (i
= 0; i
< ts
.charcnt
; ++i
)
586 sp
->chars
[sp
->charcnt
++] =
589 while (i
< ts
.timecnt
&&
591 sp
->ats
[sp
->timecnt
- 1])
593 while (i
< ts
.timecnt
&&
594 sp
->timecnt
< TZ_MAX_TIMES
) {
595 sp
->ats
[sp
->timecnt
] =
597 sp
->types
[sp
->timecnt
] =
603 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
604 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
607 if (sp
->timecnt
> 1) {
608 for (i
= 1; i
< sp
->timecnt
; ++i
)
609 if (typesequiv(sp
, sp
->types
[i
], sp
->types
[0]) &&
610 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0])) {
614 for (i
= sp
->timecnt
- 2; i
>= 0; --i
)
615 if (typesequiv(sp
, sp
->types
[sp
->timecnt
- 1],
617 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
624 ** If type 0 is is unused in transitions,
625 ** it's the type to use for early times.
627 for (i
= 0; i
< sp
->typecnt
; ++i
)
628 if (sp
->types
[i
] == 0)
630 i
= (i
>= sp
->typecnt
) ? 0 : -1;
633 ** if there are transition times
634 ** and the first transition is to a daylight time
635 ** find the standard type less than and closest to
636 ** the type of the first transition.
638 if (i
< 0 && sp
->timecnt
> 0 && sp
->ttis
[sp
->types
[0]].tt_isdst
) {
641 if (!sp
->ttis
[i
].tt_isdst
)
645 ** If no result yet, find the first standard type.
646 ** If there is none, punt to type zero.
650 while (sp
->ttis
[i
].tt_isdst
)
651 if (++i
>= sp
->typecnt
) {
665 typesequiv(const timezone_t sp
, const int a
, const int b
)
670 a
< 0 || a
>= sp
->typecnt
||
671 b
< 0 || b
>= sp
->typecnt
)
674 const struct ttinfo
* ap
= &sp
->ttis
[a
];
675 const struct ttinfo
* bp
= &sp
->ttis
[b
];
676 result
= ap
->tt_gmtoff
== bp
->tt_gmtoff
&&
677 ap
->tt_isdst
== bp
->tt_isdst
&&
678 ap
->tt_ttisstd
== bp
->tt_ttisstd
&&
679 ap
->tt_ttisgmt
== bp
->tt_ttisgmt
&&
680 strcmp(&sp
->chars
[ap
->tt_abbrind
],
681 &sp
->chars
[bp
->tt_abbrind
]) == 0;
686 static const int mon_lengths
[2][MONSPERYEAR
] = {
687 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
688 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
691 static const int year_lengths
[2] = {
692 DAYSPERNYEAR
, DAYSPERLYEAR
696 ** Given a pointer into a time zone string, scan until a character that is not
697 ** a valid character in a zone name is found. Return a pointer to that
702 getzname(const char *strp
)
706 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
713 ** Given a pointer into an extended time zone string, scan until the ending
714 ** delimiter of the zone name is located. Return a pointer to the delimiter.
716 ** As with getzname above, the legal character set is actually quite
717 ** restricted, with other characters producing undefined results.
718 ** We don't do any checking here; checking is done later in common-case code.
722 getqzname(const char *strp
, const int delim
)
726 while ((c
= *strp
) != '\0' && c
!= delim
)
732 ** Given a pointer into a time zone string, extract a number from that string.
733 ** Check that the number is within a specified range; if it is not, return
735 ** Otherwise, return a pointer to the first character not part of the number.
739 getnum(const char *strp
, int *const nump
, const int min
, const int max
)
744 if (strp
== NULL
|| !is_digit(c
= *strp
)) {
750 num
= num
* 10 + (c
- '0');
753 return NULL
; /* illegal value */
756 } while (is_digit(c
));
759 return NULL
; /* illegal value */
766 ** Given a pointer into a time zone string, extract a number of seconds,
767 ** in hh[:mm[:ss]] form, from the string.
768 ** If any error occurs, return NULL.
769 ** Otherwise, return a pointer to the first character not part of the number
774 getsecs(const char *strp
, int_fast32_t *const secsp
)
779 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
780 ** "M10.4.6/26", which does not conform to Posix,
781 ** but which specifies the equivalent of
782 ** ``02:00 on the first Sunday on or after 23 Oct''.
784 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
787 *secsp
= num
* (int_fast32_t) SECSPERHOUR
;
790 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
793 *secsp
+= num
* SECSPERMIN
;
796 /* `SECSPERMIN' allows for leap seconds. */
797 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
807 ** Given a pointer into a time zone string, extract an offset, in
808 ** [+-]hh[:mm[:ss]] form, from the string.
809 ** If any error occurs, return NULL.
810 ** Otherwise, return a pointer to the first character not part of the time.
814 getoffset(const char *strp
, int_fast32_t *const offsetp
)
821 } else if (*strp
== '+')
823 strp
= getsecs(strp
, offsetp
);
825 return NULL
; /* illegal time */
827 *offsetp
= -*offsetp
;
832 ** Given a pointer into a time zone string, extract a rule in the form
833 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
834 ** If a valid rule is not found, return NULL.
835 ** Otherwise, return a pointer to the first character not part of the rule.
839 getrule(const char *strp
, struct rule
*const rulep
)
845 rulep
->r_type
= JULIAN_DAY
;
847 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
848 } else if (*strp
== 'M') {
852 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
854 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
859 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
864 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
865 } else if (is_digit(*strp
)) {
869 rulep
->r_type
= DAY_OF_YEAR
;
870 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
871 } else return NULL
; /* invalid format */
879 strp
= getoffset(strp
, &rulep
->r_time
);
880 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
885 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
886 ** year, a rule, and the offset from UT at the time that rule takes effect,
887 ** calculate the Epoch-relative time that rule takes effect.
891 transtime(const time_t janfirst
, const int year
, const struct rule
*const rulep
,
892 const int_fast32_t offset
)
897 int d
, m1
, yy0
, yy1
, yy2
, dow
;
900 leapyear
= isleap(year
);
901 switch (rulep
->r_type
) {
905 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
907 ** In non-leap years, or if the day number is 59 or less, just
908 ** add SECSPERDAY times the day number-1 to the time of
909 ** January 1, midnight, to get the day.
911 value
= (time_t)(janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
);
912 if (leapyear
&& rulep
->r_day
>= 60)
919 ** Just add SECSPERDAY times the day number to the time of
920 ** January 1, midnight, to get the day.
922 value
= (time_t)(janfirst
+ rulep
->r_day
* SECSPERDAY
);
925 case MONTH_NTH_DAY_OF_WEEK
:
927 ** Mm.n.d - nth "dth day" of month m.
930 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
931 value
+= (time_t)(mon_lengths
[leapyear
][i
] * SECSPERDAY
);
934 ** Use Zeller's Congruence to get day-of-week of first day of
937 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
938 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
941 dow
= ((26 * m1
- 2) / 10 +
942 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
947 ** "dow" is the day-of-week of the first day of the month. Get
948 ** the day-of-month (zero-origin) of the first "dow" day of the
951 d
= rulep
->r_day
- dow
;
954 for (i
= 1; i
< rulep
->r_week
; ++i
) {
955 if (d
+ DAYSPERWEEK
>=
956 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
962 ** "d" is the day-of-month (zero-origin) of the day we want.
964 value
+= (time_t)(d
* SECSPERDAY
);
969 ** "value" is the Epoch-relative time of 00:00:00 UT on the day in
970 ** question. To get the Epoch-relative time of the specified local
971 ** time on that day, add the transition time and the current offset
974 return (time_t)(value
+ rulep
->r_time
+ offset
);
978 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
983 tzparse(timezone_t sp
, const char *name
, const int lastditch
)
985 const char * stdname
;
986 const char * dstname
;
989 int_fast32_t stdoffset
;
990 int_fast32_t dstoffset
;
992 unsigned char * typep
;
999 stdlen
= strlen(name
); /* length of standard zone name */
1001 if (stdlen
>= sizeof sp
->chars
)
1002 stdlen
= (sizeof sp
->chars
) - 1;
1008 name
= getqzname(name
, '>');
1011 stdlen
= name
- stdname
;
1014 name
= getzname(name
);
1015 stdlen
= name
- stdname
;
1019 name
= getoffset(name
, &stdoffset
);
1023 load_result
= tzload(sp
, TZDEFRULES
, FALSE
);
1024 if (load_result
!= 0)
1025 sp
->leapcnt
= 0; /* so, we're off a little */
1026 if (*name
!= '\0') {
1029 name
= getqzname(name
, '>');
1032 dstlen
= name
- dstname
;
1036 name
= getzname(name
);
1037 dstlen
= name
- dstname
; /* length of DST zone name */
1039 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1040 name
= getoffset(name
, &dstoffset
);
1043 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1044 if (*name
== '\0' && load_result
!= 0)
1045 name
= TZDEFRULESTRING
;
1046 if (*name
== ',' || *name
== ';') {
1056 if ((name
= getrule(name
, &start
)) == NULL
)
1060 if ((name
= getrule(name
, &end
)) == NULL
)
1064 sp
->typecnt
= 2; /* standard time and DST */
1066 ** Two transitions per year, from EPOCH_YEAR forward.
1068 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1069 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
1070 sp
->ttis
[0].tt_isdst
= 1;
1071 sp
->ttis
[0].tt_abbrind
= (int)(stdlen
+ 1);
1072 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
1073 sp
->ttis
[1].tt_isdst
= 0;
1074 sp
->ttis
[1].tt_abbrind
= 0;
1079 yearlim
= EPOCH_YEAR
+ YEARSPERREPEAT
;
1080 for (year
= EPOCH_YEAR
; year
< yearlim
; year
++) {
1081 int_fast32_t yearsecs
;
1083 starttime
= transtime(janfirst
, year
, &start
,
1085 endtime
= transtime(janfirst
, year
, &end
,
1087 yearsecs
= (year_lengths
[isleap(year
)]
1089 if (starttime
> endtime
1090 || (starttime
< endtime
1091 && (endtime
- starttime
1093 + (stdoffset
- dstoffset
))))) {
1094 if (&sp
->ats
[TZ_MAX_TIMES
- 2] < atp
)
1096 yearlim
= year
+ YEARSPERREPEAT
+ 1;
1097 if (starttime
> endtime
) {
1099 *typep
++ = 1; /* DST ends */
1101 *typep
++ = 0; /* DST begins */
1104 *typep
++ = 0; /* DST begins */
1106 *typep
++ = 1; /* DST ends */
1109 if (time_t_max
- janfirst
< yearsecs
)
1111 janfirst
+= yearsecs
;
1113 _DIAGASSERT(__type_fit(int, atp
- sp
->ats
));
1114 sp
->timecnt
= (int)(atp
- sp
->ats
);
1116 sp
->typecnt
= 1; /* Perpetual DST. */
1118 int_fast32_t theirstdoffset
;
1119 int_fast32_t theirdstoffset
;
1120 int_fast32_t theiroffset
;
1128 ** Initial values of theirstdoffset and theirdstoffset.
1131 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1133 if (!sp
->ttis
[j
].tt_isdst
) {
1135 -sp
->ttis
[j
].tt_gmtoff
;
1140 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1142 if (sp
->ttis
[j
].tt_isdst
) {
1144 -sp
->ttis
[j
].tt_gmtoff
;
1149 ** Initially we're assumed to be in standard time.
1152 theiroffset
= theirstdoffset
;
1154 ** Now juggle transition times and types
1155 ** tracking offsets as you do.
1157 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1159 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1160 if (sp
->ttis
[j
].tt_ttisgmt
) {
1161 /* No adjustment to transition time */
1164 ** If summer time is in effect, and the
1165 ** transition time was not specified as
1166 ** standard time, add the summer time
1167 ** offset to the transition time;
1168 ** otherwise, add the standard time
1169 ** offset to the transition time.
1172 ** Transitions from DST to DDST
1173 ** will effectively disappear since
1174 ** POSIX provides for only one DST
1177 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1178 sp
->ats
[i
] += (time_t)
1179 (dstoffset
- theirdstoffset
);
1181 sp
->ats
[i
] += (time_t)
1182 (stdoffset
- theirstdoffset
);
1185 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1186 if (!sp
->ttis
[j
].tt_isdst
)
1187 theirstdoffset
= theiroffset
;
1188 else theirdstoffset
= theiroffset
;
1191 ** Finally, fill in ttis.
1192 ** ttisstd and ttisgmt need not be handled
1194 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1195 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1196 sp
->ttis
[0].tt_isdst
= FALSE
;
1197 sp
->ttis
[0].tt_abbrind
= 0;
1198 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1199 sp
->ttis
[1].tt_isdst
= TRUE
;
1200 sp
->ttis
[1].tt_abbrind
= (int)(stdlen
+ 1);
1205 sp
->typecnt
= 1; /* only standard time */
1207 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1208 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1209 sp
->ttis
[0].tt_isdst
= 0;
1210 sp
->ttis
[0].tt_abbrind
= 0;
1212 sp
->charcnt
= (int)(stdlen
+ 1);
1214 sp
->charcnt
+= (int)(dstlen
+ 1);
1215 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1218 (void) strncpy(cp
, stdname
, stdlen
);
1222 (void) strncpy(cp
, dstname
, dstlen
);
1223 *(cp
+ dstlen
) = '\0';
1229 gmtload(timezone_t sp
)
1231 if (tzload(sp
, gmt
, TRUE
) != 0)
1232 (void) tzparse(sp
, gmt
, TRUE
);
1236 tzalloc(const char *name
)
1238 timezone_t sp
= calloc(1, sizeof *sp
);
1241 if (tzload(sp
, name
, TRUE
) != 0) {
1250 tzfree(const timezone_t sp
)
1256 tzsetwall_unlocked(void)
1262 if (lclptr
== NULL
) {
1263 int saveerrno
= errno
;
1264 lclptr
= calloc(1, sizeof *lclptr
);
1266 if (lclptr
== NULL
) {
1267 settzname(); /* all we can do */
1271 if (tzload(lclptr
, NULL
, TRUE
) != 0)
1276 #ifndef STD_INSPIRED
1278 ** A non-static declaration of tzsetwall in a system header file
1279 ** may cause a warning about this upcoming static declaration...
1282 #endif /* !defined STD_INSPIRED */
1286 rwlock_wrlock(&lcl_lock
);
1287 tzsetwall_unlocked();
1288 rwlock_unlock(&lcl_lock
);
1291 #ifndef STD_INSPIRED
1293 ** A non-static declaration of tzsetwall in a system header file
1294 ** may cause a warning about this upcoming static declaration...
1297 #endif /* !defined STD_INSPIRED */
1299 tzset_unlocked(void)
1303 name
= getenv("TZ");
1305 tzsetwall_unlocked();
1309 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1311 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1313 (void)strlcpy(lcl_TZname
, name
, sizeof(lcl_TZname
));
1315 if (lclptr
== NULL
) {
1316 int saveerrno
= errno
;
1317 lclptr
= calloc(1, sizeof *lclptr
);
1319 if (lclptr
== NULL
) {
1320 settzname(); /* all we can do */
1324 if (*name
== '\0') {
1326 ** User wants it fast rather than right.
1328 lclptr
->leapcnt
= 0; /* so, we're off a little */
1329 lclptr
->timecnt
= 0;
1330 lclptr
->typecnt
= 0;
1331 lclptr
->ttis
[0].tt_isdst
= 0;
1332 lclptr
->ttis
[0].tt_gmtoff
= 0;
1333 lclptr
->ttis
[0].tt_abbrind
= 0;
1334 (void) strlcpy(lclptr
->chars
, gmt
, sizeof(lclptr
->chars
));
1335 } else if (tzload(lclptr
, name
, TRUE
) != 0)
1336 if (name
[0] == ':' || tzparse(lclptr
, name
, FALSE
) != 0)
1337 (void) gmtload(lclptr
);
1344 rwlock_wrlock(&lcl_lock
);
1346 rwlock_unlock(&lcl_lock
);
1350 ** The easy way to behave "as if no library function calls" localtime
1351 ** is to not call it--so we drop its guts into "localsub", which can be
1352 ** freely called. (And no, the PANS doesn't require the above behavior--
1353 ** but it *is* desirable.)
1355 ** The unused offset argument is for the benefit of mktime variants.
1360 localsub(const timezone_t sp
, const time_t * const timep
, const int_fast32_t offset
,
1361 struct tm
*const tmp
)
1363 const struct ttinfo
* ttisp
;
1366 const time_t t
= *timep
;
1368 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1369 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1375 seconds
= sp
->ats
[0] - t
;
1376 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1378 years
= (time_t)((seconds
/ SECSPERREPEAT
+ 1) * YEARSPERREPEAT
);
1379 seconds
= (time_t)(years
* AVGSECSPERYEAR
);
1382 else newt
-= seconds
;
1383 if (newt
< sp
->ats
[0] ||
1384 newt
> sp
->ats
[sp
->timecnt
- 1])
1385 return NULL
; /* "cannot happen" */
1386 result
= localsub(sp
, &newt
, offset
, tmp
);
1387 if (result
== tmp
) {
1390 newy
= tmp
->tm_year
;
1394 tmp
->tm_year
= (int)newy
;
1395 if (tmp
->tm_year
!= newy
)
1400 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1401 i
= sp
->defaulttype
;
1404 int hi
= sp
->timecnt
;
1407 int mid
= (lo
+ hi
) / 2;
1409 if (t
< sp
->ats
[mid
])
1413 i
= (int) sp
->types
[lo
- 1];
1415 ttisp
= &sp
->ttis
[i
];
1417 ** To get (wrong) behavior that's compatible with System V Release 2.0
1418 ** you'd replace the statement below with
1419 ** t += ttisp->tt_gmtoff;
1420 ** timesub(&t, 0L, sp, tmp);
1422 result
= timesub(sp
, &t
, ttisp
->tt_gmtoff
, tmp
);
1423 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1425 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1427 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1428 #endif /* defined TM_ZONE */
1433 ** Re-entrant version of localtime.
1437 localtime_r(const time_t * __restrict timep
, struct tm
*tmp
)
1439 rwlock_rdlock(&lcl_lock
);
1441 tmp
= localtime_rz(lclptr
, timep
, tmp
);
1442 rwlock_unlock(&lcl_lock
);
1447 localtime(const time_t *const timep
)
1449 return localtime_r(timep
, &tm
);
1453 localtime_rz(const timezone_t sp
, const time_t * __restrict timep
, struct tm
*tmp
)
1456 tmp
= gmtsub(NULL
, timep
, 0, tmp
);
1458 tmp
= localsub(sp
, timep
, 0, tmp
);
1465 ** gmtsub is to gmtime as localsub is to localtime.
1469 gmtsub(const timezone_t sp
, const time_t *const timep
,
1470 const int_fast32_t offset
, struct tm
*const tmp
)
1474 static mutex_t gmt_mutex
= MUTEX_INITIALIZER
;
1477 mutex_lock(&gmt_mutex
);
1482 gmtptr
= calloc(1, sizeof *gmtptr
);
1487 mutex_unlock(&gmt_mutex
);
1488 result
= timesub(gmtptr
, timep
, offset
, tmp
);
1491 ** Could get fancy here and deliver something such as
1492 ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
1493 ** but this is no time for a treasure hunt.
1496 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(wildabbr
);
1499 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(gmt
);
1500 else tmp
->TM_ZONE
= gmtptr
->chars
;
1502 #endif /* defined TM_ZONE */
1507 gmtime(const time_t *const timep
)
1509 struct tm
*tmp
= gmtsub(NULL
, timep
, 0, &tm
);
1518 ** Re-entrant version of gmtime.
1522 gmtime_r(const time_t * const timep
, struct tm
*tmp
)
1524 tmp
= gmtsub(NULL
, timep
, 0, tmp
);
1535 offtime(const time_t *const timep
, long offset
)
1539 if ((offset
> 0 && offset
> INT_FAST32_MAX
) ||
1540 (offset
< 0 && offset
< INT_FAST32_MIN
)) {
1544 tmp
= gmtsub(NULL
, timep
, (int_fast32_t)offset
, &tm
);
1553 offtime_r(const time_t *timep
, long offset
, struct tm
*tmp
)
1555 if ((offset
> 0 && offset
> INT_FAST32_MAX
) ||
1556 (offset
< 0 && offset
< INT_FAST32_MIN
)) {
1560 tmp
= gmtsub(NULL
, timep
, (int_fast32_t)offset
, tmp
);
1568 #endif /* defined STD_INSPIRED */
1571 ** Return the number of leap years through the end of the given year
1572 ** where, to make the math easy, the answer for year zero is defined as zero.
1576 leaps_thru_end_of(const int y
)
1578 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1579 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1583 timesub(const timezone_t sp
, const time_t *const timep
,
1584 const int_fast32_t offset
, struct tm
*const tmp
)
1586 const struct lsinfo
* lp
;
1588 int idays
; /* unsigned would be so 2003 */
1598 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1601 if (*timep
>= lp
->ls_trans
) {
1602 if (*timep
== lp
->ls_trans
) {
1603 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1604 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1607 sp
->lsis
[i
].ls_trans
==
1608 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1609 sp
->lsis
[i
].ls_corr
==
1610 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1620 tdays
= (time_t)(*timep
/ SECSPERDAY
);
1621 rem
= (int_fast64_t) (*timep
- tdays
* SECSPERDAY
);
1622 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1628 tdelta
= tdays
/ DAYSPERLYEAR
;
1629 if (! ((! TYPE_SIGNED(time_t) || INT_MIN
<= tdelta
)
1630 && tdelta
<= INT_MAX
))
1634 idelta
= (tdays
< 0) ? -1 : 1;
1636 if (increment_overflow(&newy
, idelta
))
1638 leapdays
= leaps_thru_end_of(newy
- 1) -
1639 leaps_thru_end_of(y
- 1);
1640 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
1645 int_fast32_t seconds
;
1647 seconds
= (int_fast32_t)(tdays
* SECSPERDAY
);
1648 tdays
= (time_t)(seconds
/ SECSPERDAY
);
1649 rem
+= (int_fast64_t)(seconds
- tdays
* SECSPERDAY
);
1652 ** Given the range, we can now fearlessly cast...
1654 idays
= (int) tdays
;
1655 rem
+= offset
- corr
;
1660 while (rem
>= SECSPERDAY
) {
1665 if (increment_overflow(&y
, -1))
1667 idays
+= year_lengths
[isleap(y
)];
1669 while (idays
>= year_lengths
[isleap(y
)]) {
1670 idays
-= year_lengths
[isleap(y
)];
1671 if (increment_overflow(&y
, 1))
1675 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1677 tmp
->tm_yday
= idays
;
1679 ** The "extra" mods below avoid overflow problems.
1681 tmp
->tm_wday
= EPOCH_WDAY
+
1682 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
1683 (DAYSPERNYEAR
% DAYSPERWEEK
) +
1684 leaps_thru_end_of(y
- 1) -
1685 leaps_thru_end_of(EPOCH_YEAR
- 1) +
1687 tmp
->tm_wday
%= DAYSPERWEEK
;
1688 if (tmp
->tm_wday
< 0)
1689 tmp
->tm_wday
+= DAYSPERWEEK
;
1690 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1692 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1694 ** A positive leap second requires a special
1695 ** representation. This uses "... ??:59:60" et seq.
1697 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1698 ip
= mon_lengths
[isleap(y
)];
1699 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1700 idays
-= ip
[tmp
->tm_mon
];
1701 tmp
->tm_mday
= (int) (idays
+ 1);
1704 tmp
->TM_GMTOFF
= offset
;
1705 #endif /* defined TM_GMTOFF */
1710 ctime(const time_t *const timep
)
1713 ** Section 4.12.3.2 of X3.159-1989 requires that
1714 ** The ctime function converts the calendar time pointed to by timer
1715 ** to local time in the form of a string. It is equivalent to
1716 ** asctime(localtime(timer))
1718 struct tm
*rtm
= localtime(timep
);
1721 return asctime(rtm
);
1725 ctime_r(const time_t *const timep
, char *buf
)
1727 struct tm mytm
, *rtm
;
1729 rtm
= localtime_r(timep
, &mytm
);
1732 return asctime_r(rtm
, buf
);
1736 ctime_rz(const timezone_t sp
, const time_t * timep
, char *buf
)
1738 struct tm mytm
, *rtm
;
1740 rtm
= localtime_rz(sp
, timep
, &mytm
);
1743 return asctime_r(rtm
, buf
);
1747 ** Adapted from code provided by Robert Elz, who writes:
1748 ** The "best" way to do mktime I think is based on an idea of Bob
1749 ** Kridle's (so its said...) from a long time ago.
1750 ** It does a binary search of the time_t space. Since time_t's are
1751 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1752 ** would still be very reasonable).
1756 #define WRONG ((time_t)-1)
1757 #endif /* !defined WRONG */
1760 ** Simplified normalize logic courtesy Paul Eggert.
1764 increment_overflow(int *const ip
, int j
)
1769 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1770 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1771 ** If i < 0 there can only be overflow if i + j < INT_MIN
1772 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1774 if ((i
>= 0) ? (j
> INT_MAX
- i
) : (j
< INT_MIN
- i
))
1781 increment_overflow32(int_fast32_t *const lp
, int const m
)
1783 int_fast32_t l
= *lp
;
1785 if ((l
>= 0) ? (m
> INT_FAST32_MAX
- l
) : (m
< INT_FAST32_MIN
- l
))
1792 normalize_overflow(int *const tensptr
, int *const unitsptr
, const int base
)
1796 tensdelta
= (*unitsptr
>= 0) ?
1797 (*unitsptr
/ base
) :
1798 (-1 - (-1 - *unitsptr
) / base
);
1799 *unitsptr
-= tensdelta
* base
;
1800 return increment_overflow(tensptr
, tensdelta
);
1804 normalize_overflow32(int_fast32_t *const tensptr
, int *const unitsptr
,
1809 tensdelta
= (*unitsptr
>= 0) ?
1810 (*unitsptr
/ base
) :
1811 (-1 - (-1 - *unitsptr
) / base
);
1812 *unitsptr
-= tensdelta
* base
;
1813 return increment_overflow32(tensptr
, tensdelta
);
1817 tmcomp(const struct tm
*const atmp
, const struct tm
*const btmp
)
1821 if (atmp
->tm_year
!= btmp
->tm_year
)
1822 return atmp
->tm_year
< btmp
->tm_year
? -1 : 1;
1823 if ((result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1824 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1825 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1826 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1827 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1832 time2sub(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
1833 const int_fast32_t offset
, int *const okayp
, const int do_norm_secs
)
1841 #ifdef NO_ERROR_IN_DST_GAP
1847 struct tm yourtm
, mytm
;
1851 #ifdef NO_ERROR_IN_DST_GAP
1855 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1859 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1861 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1864 if (normalize_overflow32(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1867 ** Turn y into an actual year number for now.
1868 ** It is converted back to an offset from TM_YEAR_BASE later.
1870 if (increment_overflow32(&y
, TM_YEAR_BASE
))
1872 while (yourtm
.tm_mday
<= 0) {
1873 if (increment_overflow32(&y
, -1))
1875 li
= y
+ (1 < yourtm
.tm_mon
);
1876 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1878 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1879 li
= y
+ (1 < yourtm
.tm_mon
);
1880 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1881 if (increment_overflow32(&y
, 1))
1885 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1886 if (yourtm
.tm_mday
<= i
)
1888 yourtm
.tm_mday
-= i
;
1889 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1891 if (increment_overflow32(&y
, 1))
1895 if (increment_overflow32(&y
, -TM_YEAR_BASE
))
1897 yourtm
.tm_year
= (int)y
;
1898 if (yourtm
.tm_year
!= y
)
1900 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1902 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1904 ** We can't set tm_sec to 0, because that might push the
1905 ** time below the minimum representable time.
1906 ** Set tm_sec to 59 instead.
1907 ** This assumes that the minimum representable time is
1908 ** not in the same minute that a leap second was deleted from,
1909 ** which is a safer assumption than using 58 would be.
1911 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1913 saved_seconds
= yourtm
.tm_sec
;
1914 yourtm
.tm_sec
= SECSPERMIN
- 1;
1916 saved_seconds
= yourtm
.tm_sec
;
1920 ** Do a binary search (this works whatever time_t's type is).
1922 /* LINTED const not */
1923 if (!TYPE_SIGNED(time_t)) {
1928 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
1932 #ifdef NO_ERROR_IN_DST_GAP
1936 t
= lo
/ 2 + hi
/ 2;
1941 if ((*funcp
)(sp
, &t
, offset
, &mytm
) == NULL
) {
1943 ** Assume that t is too extreme to be represented in
1944 ** a struct tm; arrange things so that it is less
1945 ** extreme on the next pass.
1947 dir
= (t
> 0) ? 1 : -1;
1948 } else dir
= tmcomp(&mytm
, &yourtm
);
1951 if (t
== time_t_max
)
1955 } else if (t
== hi
) {
1956 if (t
== time_t_min
)
1961 #ifdef NO_ERROR_IN_DST_GAP
1962 if (ilo
!= lo
&& lo
- 1 == hi
&& yourtm
.tm_isdst
< 0 &&
1964 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1965 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1967 if (sp
->ttis
[j
].tt_isdst
==
1968 sp
->ttis
[i
].tt_isdst
)
1970 off
= sp
->ttis
[j
].tt_gmtoff
-
1971 sp
->ttis
[i
].tt_gmtoff
;
1972 yourtm
.tm_sec
+= off
< 0 ?
1986 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1989 ** Right time, wrong type.
1990 ** Hunt for right time, right type.
1991 ** It's okay to guess wrong since the guess
1996 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1997 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1999 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
2000 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
2002 newt
= (time_t)(t
+ sp
->ttis
[j
].tt_gmtoff
-
2003 sp
->ttis
[i
].tt_gmtoff
);
2004 if ((*funcp
)(sp
, &newt
, offset
, &mytm
) == NULL
)
2006 if (tmcomp(&mytm
, &yourtm
) != 0)
2008 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
2020 newt
= t
+ saved_seconds
;
2021 if ((newt
< t
) != (saved_seconds
< 0))
2024 if ((*funcp
)(sp
, &t
, offset
, tmp
)) {
2037 time2(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
2038 const int_fast32_t offset
, int *const okayp
)
2043 ** First try without normalization of seconds
2044 ** (in case tm_sec contains a value associated with a leap second).
2045 ** If that fails, try with normalization of seconds.
2047 t
= time2sub(sp
, tmp
, funcp
, offset
, okayp
, FALSE
);
2048 return *okayp
? t
: time2sub(sp
, tmp
, funcp
, offset
, okayp
, TRUE
);
2052 time1(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
2053 const int_fast32_t offset
)
2057 int sameind
, otherind
;
2060 int seen
[TZ_MAX_TYPES
];
2061 int types
[TZ_MAX_TYPES
];
2068 if (tmp
->tm_isdst
> 1)
2070 t
= time2(sp
, tmp
, funcp
, offset
, &okay
);
2073 ** PCTS code courtesy Grant Sullivan.
2077 if (tmp
->tm_isdst
< 0)
2078 tmp
->tm_isdst
= 0; /* reset to std and try again */
2079 #endif /* defined PCTS */
2081 if (okay
|| tmp
->tm_isdst
< 0)
2083 #endif /* !defined PCTS */
2085 ** We're supposed to assume that somebody took a time of one type
2086 ** and did some math on it that yielded a "struct tm" that's bad.
2087 ** We try to divine the type they started from and adjust to the
2094 for (i
= 0; i
< sp
->typecnt
; ++i
)
2097 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
2098 if (!seen
[sp
->types
[i
]]) {
2099 seen
[sp
->types
[i
]] = TRUE
;
2100 types
[nseen
++] = sp
->types
[i
];
2102 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2103 samei
= types
[sameind
];
2104 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2106 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2107 otheri
= types
[otherind
];
2108 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
2110 tmp
->tm_sec
+= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2111 sp
->ttis
[samei
].tt_gmtoff
);
2112 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2113 t
= time2(sp
, tmp
, funcp
, offset
, &okay
);
2116 tmp
->tm_sec
-= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2117 sp
->ttis
[samei
].tt_gmtoff
);
2118 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2126 mktime_z(const timezone_t sp
, struct tm
*const tmp
)
2130 t
= time1(NULL
, tmp
, gmtsub
, 0);
2132 t
= time1(sp
, tmp
, localsub
, 0);
2137 mktime(struct tm
*const tmp
)
2141 rwlock_wrlock(&lcl_lock
);
2143 result
= mktime_z(lclptr
, tmp
);
2144 rwlock_unlock(&lcl_lock
);
2151 timelocal_z(const timezone_t sp
, struct tm
*const tmp
)
2154 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2155 return mktime_z(sp
, tmp
);
2159 timelocal(struct tm
*const tmp
)
2162 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2167 timegm(struct tm
*const tmp
)
2173 t
= time1(gmtptr
, tmp
, gmtsub
, 0);
2178 timeoff(struct tm
*const tmp
, long offset
)
2182 if ((offset
> 0 && offset
> INT_FAST32_MAX
) ||
2183 (offset
< 0 && offset
< INT_FAST32_MIN
)) {
2189 t
= time1(gmtptr
, tmp
, gmtsub
, (int_fast32_t)offset
);
2193 #endif /* defined STD_INSPIRED */
2198 ** The following is supplied for compatibility with
2199 ** previous versions of the CMUCS runtime library.
2203 gtime(struct tm
*const tmp
)
2205 const time_t t
= mktime(tmp
);
2212 #endif /* defined CMUCS */
2215 ** XXX--is the below the right way to conditionalize??
2221 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2222 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2223 ** is not the case if we are accounting for leap seconds.
2224 ** So, we provide the following conversion routines for use
2225 ** when exchanging timestamps with POSIX conforming systems.
2229 leapcorr(const timezone_t sp
, time_t *timep
)
2237 if (*timep
>= lp
->ls_trans
)
2244 time2posix_z(const timezone_t sp
, time_t t
)
2246 return (time_t)(t
- leapcorr(sp
, &t
));
2250 time2posix(time_t t
)
2253 rwlock_wrlock(&lcl_lock
);
2255 result
= (time_t)(t
- leapcorr(lclptr
, &t
));
2256 rwlock_unlock(&lcl_lock
);
2261 posix2time_z(const timezone_t sp
, time_t t
)
2267 ** For a positive leap second hit, the result
2268 ** is not unique. For a negative leap second
2269 ** hit, the corresponding time doesn't exist,
2270 ** so we return an adjacent second.
2272 x
= (time_t)(t
+ leapcorr(sp
, &t
));
2273 y
= (time_t)(x
- leapcorr(sp
, &x
));
2277 y
= (time_t)(x
- leapcorr(sp
, &x
));
2285 y
= (time_t)(x
- leapcorr(sp
, &x
));
2297 posix2time(time_t t
)
2301 rwlock_wrlock(&lcl_lock
);
2303 result
= posix2time_z(lclptr
, t
);
2304 rwlock_unlock(&lcl_lock
);
2308 #endif /* defined STD_INSPIRED */