2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
9 static char elsieid
[] __unused
= "@(#)localtime.c 7.78";
10 #endif /* !defined NOID */
11 #endif /* !defined lint */
12 __FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.40 2004/08/24 00:15:37 peter Exp $");
15 ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
16 ** POSIX-style TZ environment variable handling from Guy Harris
22 #include "namespace.h"
23 #include <sys/types.h>
30 //#define NOTIFY_TZ_DEBUG
31 //#define NOTIFY_TZ_DEBUG_FILE "/var/log/localtime.debug"
32 //#define NOTIFY_TZ_LOG "/var/log/localtime.log"
33 /* force ALL_STATE if NOTIFY_TZ is set */
36 #endif /* ALL_STATE */
37 #include <mach/mach_init.h>
40 #endif /* NOTIFY_TZ */
42 #include "un-namespace.h"
46 #include "libc_private.h"
48 #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
49 #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
52 ** SunOS 4.1.1 headers lack O_BINARY.
56 #define OPEN_MODE (O_RDONLY | O_BINARY)
57 #endif /* defined O_BINARY */
59 #define OPEN_MODE O_RDONLY
60 #endif /* !defined O_BINARY */
64 ** Someone might make incorrect use of a time zone abbreviation:
65 ** 1. They might reference tzname[0] before calling tzset (explicitly
67 ** 2. They might reference tzname[1] before calling tzset (explicitly
69 ** 3. They might reference tzname[1] after setting to a time zone
70 ** in which Daylight Saving Time is never observed.
71 ** 4. They might reference tzname[0] after setting to a time zone
72 ** in which Standard Time is never observed.
73 ** 5. They might reference tm.TM_ZONE after calling offtime.
74 ** What's best to do in the above cases is open to debate;
75 ** for now, we just set things up so that in any of the five cases
76 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
77 ** string "tzname[0] used before set", and similarly for the other cases.
78 ** And another: initialize tzname[0] to "ERA", with an explanation in the
79 ** manual page of what this "time zone abbreviation" means (doing this so
80 ** that tzname[0] has the "normal" length of three characters).
83 #endif /* !defined WILDABBR */
85 static char wildabbr
[] = "WILDABBR";
88 * In June 2004 it was decided UTC was a more appropriate default time
92 static const char gmt
[] = "UTC";
95 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
96 ** We default to US rules as of 1999-08-17.
97 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
98 ** implementation dependent; for historical reasons, US rules are a
101 #ifndef TZDEFRULESTRING
102 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
103 #endif /* !defined TZDEFDST */
105 struct ttinfo
{ /* time type information */
106 long tt_gmtoff
; /* UTC offset in seconds */
107 int tt_isdst
; /* used to set tm_isdst */
108 int tt_abbrind
; /* abbreviation list index */
109 int tt_ttisstd
; /* TRUE if transition is std time */
110 int tt_ttisgmt
; /* TRUE if transition is UTC */
113 struct lsinfo
{ /* leap second information */
114 time_t ls_trans
; /* transition time */
115 long ls_corr
; /* correction to apply */
118 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
121 #define MY_TZNAME_MAX TZNAME_MAX
122 #endif /* defined TZNAME_MAX */
124 #define MY_TZNAME_MAX 255
125 #endif /* !defined TZNAME_MAX */
132 time_t ats
[TZ_MAX_TIMES
];
133 unsigned char types
[TZ_MAX_TIMES
];
134 struct ttinfo ttis
[TZ_MAX_TYPES
];
135 char chars
[BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
136 (2 * (MY_TZNAME_MAX
+ 1)))];
137 struct lsinfo lsis
[TZ_MAX_LEAPS
];
141 int r_type
; /* type of rule--see below */
142 int r_day
; /* day number of rule */
143 int r_week
; /* week number of rule */
144 int r_mon
; /* month number of rule */
145 long r_time
; /* transition time of rule */
148 #define JULIAN_DAY 0 /* Jn - Julian day */
149 #define DAY_OF_YEAR 1 /* n - day of year */
150 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
159 #define NOTIFY_TZ_NAME "com.apple.system.timezone"
160 #endif /* NOTIFY_TZ */
163 ** Prototypes for static functions.
165 #define localsub _st_localsub
166 #define time1 _st_time1
167 #define tzset_basic _st_tzset_basic
170 struct tm
* localsub(const time_t * timep
, long offset
,
172 #else /* !__LP64__ */
173 void localsub(const time_t * timep
, long offset
,
175 #endif /* __LP64__ */
177 time_t time1(struct tm
* tmp
,
179 struct tm
*(*funcp
) (const time_t *,
181 #else /* !__LP64__ */
182 void(*funcp
) (const time_t *,
184 #endif /* __LP64__ */
188 void tzset_basic(void);
190 #define lcl_mutex _st_lcl_mutex
192 #if !BUILDING_VARIANT
193 static long detzcode(const char * codep
);
194 static const char * getzname(const char * strp
, char **name
, size_t *len
);
195 static const char * getnum(const char * strp
, int * nump
, int min
,
197 static const char * getsecs(const char * strp
, long * secsp
);
198 static const char * getoffset(const char * strp
, long * offsetp
);
199 static const char * getrule(const char * strp
, struct rule
* rulep
);
200 static void gmtload(struct state
* sp
);
202 static struct tm
* gmtsub(const time_t * timep
, long offset
,
204 #else /* !__LP64__ */
205 static void gmtsub(const time_t * timep
, long offset
,
207 #endif /* __LP64__ */
208 static int increment_overflow(int * number
, int delta
);
209 static int normalize_overflow(int * tensptr
, int * unitsptr
,
212 static void notify_check_tz(notify_tz_t
*p
);
213 static void notify_register_tz(char *file
, notify_tz_t
*p
);
214 #endif /* NOTIFY_TZ */
215 static void settzname(void);
216 static time_t time2(struct tm
*tmp
,
218 struct tm
*(*funcp
) (const time_t *,
220 #else /* !__LP64__ */
221 void(*funcp
) (const time_t *,
223 #endif /* __LP64__ */
224 long offset
, int * okayp
, int unix03
);
225 static time_t time2sub(struct tm
*tmp
,
227 struct tm
*(*funcp
) (const time_t *,
229 #else /* !__LP64__ */
230 void(*funcp
) (const time_t *,
232 #endif /* __LP64__ */
233 long offset
, int * okayp
, int do_norm_secs
,
236 static struct tm
* timesub(const time_t * timep
, long offset
,
237 const struct state
* sp
, struct tm
* tmp
);
238 #else /* !__LP64__ */
239 static void timesub(const time_t * timep
, long offset
,
240 const struct state
* sp
, struct tm
* tmp
);
241 #endif /* __LP64__ */
242 static int tmcomp(const struct tm
* atmp
,
243 const struct tm
* btmp
);
244 static time_t transtime(time_t janfirst
, int year
,
245 const struct rule
* rulep
, long offset
);
246 static int tzload(const char * name
, struct state
* sp
);
247 static int tzparse(const char * name
, struct state
* sp
,
251 static struct state
* lclptr
;
252 static struct state
* gmtptr
;
253 #endif /* defined ALL_STATE */
256 static struct state lclmem
;
257 static struct state gmtmem
;
258 #define lclptr (&lclmem)
259 #define gmtptr (&gmtmem)
260 #endif /* State Farm */
262 #ifndef TZ_STRLEN_MAX
263 #define TZ_STRLEN_MAX 255
264 #endif /* !defined TZ_STRLEN_MAX */
266 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
268 #define lcl_is_set (lcl_notify.is_set)
269 #define gmt_is_set (gmt_notify.is_set)
270 #else /* ! NOTIFY_TZ */
271 static int lcl_is_set
;
272 static int gmt_is_set
;
273 #endif /* NOTIFY_TZ */
274 __private_extern__ pthread_mutex_t lcl_mutex
= PTHREAD_MUTEX_INITIALIZER
;
275 static pthread_mutex_t gmt_mutex
= PTHREAD_MUTEX_INITIALIZER
;
283 ** Section 4.12.3 of X3.159-1989 requires that
284 ** Except for the strftime function, these functions [asctime,
285 ** ctime, gmtime, localtime] return values in one of two static
286 ** objects: a broken-down time structure and an array of char.
287 ** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
296 __private_extern__
void _st_set_timezone(long);
297 #endif /* defined USG_COMPAT */
300 __private_extern__
long __darwin_altzone
= 0;
301 #define altzone __darwin_altzone
302 #endif /* defined ALTZONE */
305 #ifdef NOTIFY_TZ_DEBUG
306 #ifdef NOTIFY_TZ_DEBUG_FILE
307 #define NOTIFY_TZ_PRINTF(fmt, args...) \
309 FILE *_notify_tz_fp_; \
310 if((_notify_tz_fp_ = fopen(NOTIFY_TZ_DEBUG_FILE, "a")) != NULL) { \
311 fprintf(_notify_tz_fp_, "%d: " fmt, getpid(), ## args); \
312 fclose(_notify_tz_fp_); \
315 #else /* ! NOTIFY_TZ_DEBUG_FILE */
316 #define NOTIFY_TZ_PRINTF(args...) fprintf(stdout, ## args)
317 #endif /* NOTIFY_TZ_DEBUG_FILE */
318 #endif /* NOTIFY_TZ_DEBUG */
320 #define NOTIFY_LOG(fmt, args...) \
322 FILE *_notify_log_fp_; \
323 if((_notify_log_fp_ = fopen(NOTIFY_TZ_LOG, "a")) != NULL) { \
324 fprintf(_notify_log_fp_, "%d: " fmt, getpid(), ## args); \
325 fclose(_notify_log_fp_); \
328 #endif /* NOTIFY_TZ_LOG */
329 /*--------------------------------------------------------------------
330 * __notify_78945668_info__ is a global variable (defined in Libnotify)
331 * that can be used to disable the notify mechanism. Set to a negative
332 * value to disable. It can then be set back to zero to re-enable.
333 *-------------------------------------------------------------------- */
334 extern int __notify_78945668_info__
;
336 /*--------------------------------------------------------------------
337 * fullname is used to pass the actual path of the timezone file to the
338 * notify routines. If it is a nil string, that means no timezone file
340 *-------------------------------------------------------------------- */
341 static char * fullname
= NULL
;
343 static notify_tz_t gmt_notify
= {-1, 0, 0};
344 static notify_tz_t lcl_notify
= {-1, 0, 0};
345 static char notify_tz_name
[] = NOTIFY_TZ_NAME
;
346 #endif /* NOTIFY_TZ */
350 const char * const codep
;
355 result
= (codep
[0] & 0x80) ? ~0L : 0L;
356 for (i
= 0; i
< 4; ++i
)
357 result
= (result
<< 8) | (codep
[i
] & 0xff);
364 struct state
* sp
= lclptr
;
367 tzname
[0] = wildabbr
;
368 tzname
[1] = wildabbr
;
372 #endif /* defined USG_COMPAT */
375 #endif /* defined ALTZONE */
378 tzname
[0] = tzname
[1] = (char *)gmt
;
381 #endif /* defined ALL_STATE */
382 for (i
= 0; i
< sp
->typecnt
; ++i
) {
383 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
385 tzname
[ttisp
->tt_isdst
] =
386 &sp
->chars
[ttisp
->tt_abbrind
];
390 if (i
== 0 || !ttisp
->tt_isdst
)
391 _st_set_timezone(-(ttisp
->tt_gmtoff
));
392 #endif /* defined USG_COMPAT */
394 if (i
== 0 || ttisp
->tt_isdst
)
395 altzone
= -(ttisp
->tt_gmtoff
);
396 #endif /* defined ALTZONE */
399 ** And to get the latest zone names into tzname. . .
401 for (i
= 0; i
< sp
->timecnt
; ++i
) {
402 const struct ttinfo
* const ttisp
=
406 tzname
[ttisp
->tt_isdst
] =
407 &sp
->chars
[ttisp
->tt_abbrind
];
413 notify_check_tz(notify_tz_t
*p
)
418 if (__notify_78945668_info__
< 0) {
419 #ifdef NOTIFY_TZ_DEBUG
420 if(!p
->notify_was_off
) NOTIFY_TZ_PRINTF("notify_check_tz: setting %s_notify->notify_was_off\n", (p
== &lcl_notify
? "lcl" : "gmt"));
421 #endif /* NOTIFY_TZ_DEBUG */
422 p
->notify_was_off
= 1;
425 /* force rereading the timezone file if notify was off */
426 if (p
->notify_was_off
) {
427 #ifdef NOTIFY_TZ_DEBUG
428 NOTIFY_TZ_PRINTF("notify_check_tz: saw %s_notify->notify_was_off\n", (p
== &lcl_notify
? "lcl" : "gmt"));
429 #endif /* NOTIFY_TZ_DEBUG */
431 p
->notify_was_off
= 0;
436 nstat
= notify_check(p
->token
, &ncheck
);
437 if (nstat
|| ncheck
) {
439 #ifdef NOTIFY_TZ_DEBUG
440 NOTIFY_TZ_PRINTF("notify_check_tz: %s changed\n", (p
== &lcl_notify
) ? "lcl" : "gmt");
441 #endif /* NOTIFY_TZ_DEBUG */
443 #ifdef NOTIFY_TZ_DEBUG
444 NOTIFY_TZ_PRINTF("notify_check_tz: %s unchanged\n", (p
== &lcl_notify
) ? "lcl" : "gmt");
445 #endif /* NOTIFY_TZ_DEBUG */
448 extern uint32_t notify_monitor_file(int token
, char *path
, int flags
);
451 notify_register_tz(char *file
, notify_tz_t
*p
)
457 if (__notify_78945668_info__
< 0)
459 /*----------------------------------------------------------------
460 * Since we don't record the last time zone filename, just cancel
461 * (which should remove the file monitor) and setup from scratch
462 *----------------------------------------------------------------*/
464 notify_cancel(p
->token
);
465 if (!file
|| *file
== 0) {
466 /* no time zone file to monitor */
470 /*----------------------------------------------------------------
471 * Just use com.apple.system.timezone if the path is /etc/localtime.
472 * Otherwise use com.apple.system.timezone.<fullpath>
473 *----------------------------------------------------------------*/
474 if (TZDEFAULT
&& strcmp(file
, TZDEFAULT
) == 0)
475 name
= notify_tz_name
;
477 name
= alloca(sizeof(notify_tz_name
) + strlen(file
) + 1);
482 strcpy(name
, notify_tz_name
);
486 #ifdef NOTIFY_TZ_DEBUG
487 NOTIFY_TZ_PRINTF("notify_register_tz: file=%s name=%s\n", file
, name
);
488 #endif /* NOTIFY_TZ_DEBUG */
489 nstat
= notify_register_check(name
, &p
->token
);
493 #ifdef NOTIFY_TZ_DEBUG
494 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_register_check failed: %u\n", nstat
);
495 #endif /* NOTIFY_TZ_DEBUG */
497 NOTIFY_LOG("notify_register_check(%s) failed: %u\n", name
, nstat
);
498 #endif /* NOTIFY_TZ_LOG */
501 /* don't need to request monitoring /etc/localtime */
502 if (name
!= notify_tz_name
) {
503 #ifdef NOTIFY_TZ_DEBUG
504 NOTIFY_TZ_PRINTF("notify_register_tz: monitor %s\n", file
);
505 #endif /* NOTIFY_TZ_DEBUG */
506 nstat
= notify_monitor_file(p
->token
, file
, 0);
508 notify_cancel(p
->token
);
511 #ifdef NOTIFY_TZ_DEBUG
512 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_monitor_file failed: %u\n", nstat
);
513 #endif /* NOTIFY_TZ_DEBUG */
515 NOTIFY_LOG("notify_monitor_file(%s) failed: %u\n", file
, nstat
);
516 #endif /* NOTIFY_TZ_LOG */
520 notify_check(p
->token
, &ncheck
); /* this always returns true */
522 #endif /* NOTIFY_TZ */
527 struct state
* const sp
;
533 #ifdef NOTIFY_TZ_DEBUG
534 NOTIFY_TZ_PRINTF("tzload: name=%s\n", name
);
535 #endif /* NOTIFY_TZ_DEBUG */
536 /* XXX The following is from OpenBSD, and I'm not sure it is correct */
537 if (name
!= NULL
&& issetugid() != 0)
538 if ((name
[0] == ':' && name
[1] == '/') ||
539 name
[0] == '/' || strchr(name
, '.'))
541 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
547 ** Section 4.9.1 of the C standard says that
548 ** "FILENAME_MAX expands to an integral constant expression
549 ** that is the size needed for an array of char large enough
550 ** to hold the longest file name string that the implementation
551 ** guarantees can be opened."
555 fullname
= malloc(FILENAME_MAX
+ 1);
559 #else /* ! NOTIFY_TZ */
560 char fullname
[FILENAME_MAX
+ 1];
561 #endif /* NOTIFY_TZ */
565 doaccess
= name
[0] == '/';
567 if ((p
= TZDIR
) == NULL
)
570 if ((strlen(p
) + 1 + strlen(name
) + 1) >= (FILENAME_MAX
+ 1))
571 #else /* ! NOTIFY_TZ */
572 if ((strlen(p
) + 1 + strlen(name
) + 1) >= sizeof fullname
)
573 #endif /* NOTIFY_TZ */
575 (void) strcpy(fullname
, p
);
576 (void) strcat(fullname
, "/");
577 (void) strcat(fullname
, name
);
579 ** Set doaccess if '.' (as in "../") shows up in name.
581 if (strchr(name
, '.') != NULL
)
587 strcpy(fullname
, name
);
588 #endif /* NOTIFY_TZ */
589 if (doaccess
&& access(name
, R_OK
) != 0)
591 if ((fid
= _open(name
, OPEN_MODE
)) == -1)
593 if ((_fstat(fid
, &stab
) < 0) || !S_ISREG(stab
.st_mode
)) {
599 struct tzhead
* tzhp
;
601 struct tzhead tzhead
;
602 char buf
[sizeof *sp
+ sizeof *tzhp
];
607 #ifdef NOTIFY_TZ_DEBUG
608 NOTIFY_TZ_PRINTF("tzload: reading %s\n", name
);
609 #endif /* NOTIFY_TZ_DEBUG */
610 i
= _read(fid
, u
.buf
, sizeof u
.buf
);
611 if (_close(fid
) != 0)
613 ttisstdcnt
= (int) detzcode(u
.tzhead
.tzh_ttisstdcnt
);
614 ttisgmtcnt
= (int) detzcode(u
.tzhead
.tzh_ttisgmtcnt
);
615 sp
->leapcnt
= (int) detzcode(u
.tzhead
.tzh_leapcnt
);
616 sp
->timecnt
= (int) detzcode(u
.tzhead
.tzh_timecnt
);
617 sp
->typecnt
= (int) detzcode(u
.tzhead
.tzh_typecnt
);
618 sp
->charcnt
= (int) detzcode(u
.tzhead
.tzh_charcnt
);
619 p
= u
.tzhead
.tzh_charcnt
+ sizeof u
.tzhead
.tzh_charcnt
;
620 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
621 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
622 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
623 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
624 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
625 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
627 if (i
- (p
- u
.buf
) < sp
->timecnt
* 4 + /* ats */
628 sp
->timecnt
+ /* types */
629 sp
->typecnt
* (4 + 2) + /* ttinfos */
630 sp
->charcnt
+ /* chars */
631 sp
->leapcnt
* (4 + 4) + /* lsinfos */
632 ttisstdcnt
+ /* ttisstds */
633 ttisgmtcnt
) /* ttisgmts */
635 for (i
= 0; i
< sp
->timecnt
; ++i
) {
636 sp
->ats
[i
] = detzcode(p
);
639 for (i
= 0; i
< sp
->timecnt
; ++i
) {
640 sp
->types
[i
] = (unsigned char) *p
++;
641 if (sp
->types
[i
] >= sp
->typecnt
)
644 for (i
= 0; i
< sp
->typecnt
; ++i
) {
645 struct ttinfo
* ttisp
;
647 ttisp
= &sp
->ttis
[i
];
648 ttisp
->tt_gmtoff
= detzcode(p
);
650 ttisp
->tt_isdst
= (unsigned char) *p
++;
651 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
653 ttisp
->tt_abbrind
= (unsigned char) *p
++;
654 if (ttisp
->tt_abbrind
< 0 ||
655 ttisp
->tt_abbrind
> sp
->charcnt
)
658 for (i
= 0; i
< sp
->charcnt
; ++i
)
660 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
661 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
662 struct lsinfo
* lsisp
;
664 lsisp
= &sp
->lsis
[i
];
665 lsisp
->ls_trans
= detzcode(p
);
667 lsisp
->ls_corr
= detzcode(p
);
670 for (i
= 0; i
< sp
->typecnt
; ++i
) {
671 struct ttinfo
* ttisp
;
673 ttisp
= &sp
->ttis
[i
];
675 ttisp
->tt_ttisstd
= FALSE
;
677 ttisp
->tt_ttisstd
= *p
++;
678 if (ttisp
->tt_ttisstd
!= TRUE
&&
679 ttisp
->tt_ttisstd
!= FALSE
)
683 for (i
= 0; i
< sp
->typecnt
; ++i
) {
684 struct ttinfo
* ttisp
;
686 ttisp
= &sp
->ttis
[i
];
688 ttisp
->tt_ttisgmt
= FALSE
;
690 ttisp
->tt_ttisgmt
= *p
++;
691 if (ttisp
->tt_ttisgmt
!= TRUE
&&
692 ttisp
->tt_ttisgmt
!= FALSE
)
700 static const int mon_lengths
[2][MONSPERYEAR
] = {
701 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
702 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
705 static const int year_lengths
[2] = {
706 DAYSPERNYEAR
, DAYSPERLYEAR
710 ** Given a pointer into a time zone string, scan until a character that is not
711 ** a valid character in a zone name is found. Return a pointer to that
716 getzname(strp
, name
, len
)
724 if (*strp
== '<' && (ket
= strchr(strp
, '>')) != NULL
) {
725 *name
= (char *)(strp
+ 1);
726 *len
= ket
- strp
- 1;
729 *name
= (char *)strp
;
730 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
738 ** Given a pointer into a time zone string, extract a number from that string.
739 ** Check that the number is within a specified range; if it is not, return
741 ** Otherwise, return a pointer to the first character not part of the number.
745 getnum(strp
, nump
, min
, max
)
754 if (strp
== NULL
|| !is_digit(c
= *strp
))
758 num
= num
* 10 + (c
- '0');
760 return NULL
; /* illegal value */
762 } while (is_digit(c
));
764 return NULL
; /* illegal value */
770 ** Given a pointer into a time zone string, extract a number of seconds,
771 ** in hh[:mm[:ss]] form, from the string.
772 ** If any error occurs, return NULL.
773 ** Otherwise, return a pointer to the first character not part of the number
785 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
786 ** "M10.4.6/26", which does not conform to Posix,
787 ** but which specifies the equivalent of
788 ** ``02:00 on the first Sunday on or after 23 Oct''.
790 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
793 *secsp
= num
* (long) SECSPERHOUR
;
796 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
799 *secsp
+= num
* SECSPERMIN
;
802 /* `SECSPERMIN' allows for leap seconds. */
803 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
813 ** Given a pointer into a time zone string, extract an offset, in
814 ** [+-]hh[:mm[:ss]] form, from the string.
815 ** If any error occurs, return NULL.
816 ** Otherwise, return a pointer to the first character not part of the time.
820 getoffset(strp
, offsetp
)
822 long * const offsetp
;
829 } else if (*strp
== '+')
831 strp
= getsecs(strp
, offsetp
);
833 return NULL
; /* illegal time */
835 *offsetp
= -*offsetp
;
840 ** Given a pointer into a time zone string, extract a rule in the form
841 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
842 ** If a valid rule is not found, return NULL.
843 ** Otherwise, return a pointer to the first character not part of the rule.
849 struct rule
* const rulep
;
855 rulep
->r_type
= JULIAN_DAY
;
857 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
858 } else if (*strp
== 'M') {
862 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
864 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
869 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
874 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
875 } else if (is_digit(*strp
)) {
879 rulep
->r_type
= DAY_OF_YEAR
;
880 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
881 } else return NULL
; /* invalid format */
889 strp
= getsecs(strp
, &rulep
->r_time
);
890 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
895 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
896 ** year, a rule, and the offset from UTC at the time that rule takes effect,
897 ** calculate the Epoch-relative time that rule takes effect.
901 transtime(janfirst
, year
, rulep
, offset
)
902 const time_t janfirst
;
904 const struct rule
* const rulep
;
910 int d
, m1
, yy0
, yy1
, yy2
, dow
;
913 leapyear
= isleap(year
);
914 switch (rulep
->r_type
) {
918 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
920 ** In non-leap years, or if the day number is 59 or less, just
921 ** add SECSPERDAY times the day number-1 to the time of
922 ** January 1, midnight, to get the day.
924 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
925 if (leapyear
&& rulep
->r_day
>= 60)
932 ** Just add SECSPERDAY times the day number to the time of
933 ** January 1, midnight, to get the day.
935 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
938 case MONTH_NTH_DAY_OF_WEEK
:
940 ** Mm.n.d - nth "dth day" of month m.
943 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
944 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
947 ** Use Zeller's Congruence to get day-of-week of first day of
950 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
951 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
954 dow
= ((26 * m1
- 2) / 10 +
955 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
960 ** "dow" is the day-of-week of the first day of the month. Get
961 ** the day-of-month (zero-origin) of the first "dow" day of the
964 d
= rulep
->r_day
- dow
;
967 for (i
= 1; i
< rulep
->r_week
; ++i
) {
968 if (d
+ DAYSPERWEEK
>=
969 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
975 ** "d" is the day-of-month (zero-origin) of the day we want.
977 value
+= d
* SECSPERDAY
;
982 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
983 ** question. To get the Epoch-relative time of the specified local
984 ** time on that day, add the transition time and the current offset
987 return value
+ rulep
->r_time
+ offset
;
991 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
996 tzparse(name
, sp
, lastditch
)
998 struct state
* const sp
;
1001 const char * stdname
;
1002 const char * dstname
;
1008 unsigned char * typep
;
1012 INITIALIZE(dstname
);
1015 stdlen
= strlen(name
); /* length of standard zone name */
1017 if (stdlen
>= sizeof sp
->chars
)
1018 stdlen
= (sizeof sp
->chars
) - 1;
1021 name
= getzname(name
, (char **)&stdname
, &stdlen
);
1025 return -1; /* was "stdoffset = 0;" */
1027 name
= getoffset(name
, &stdoffset
);
1032 load_result
= tzload(TZDEFRULES
, sp
);
1034 *fullname
= 0; /* mark fullname as invalid */
1035 #endif /* NOTIFY_TZ */
1036 if (load_result
!= 0)
1037 sp
->leapcnt
= 0; /* so, we're off a little */
1038 if (*name
!= '\0') {
1040 name
= getzname(name
, (char **)&dstname
, &dstlen
);
1043 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1044 name
= getoffset(name
, &dstoffset
);
1047 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1048 if (*name
== '\0' && load_result
!= 0)
1049 name
= TZDEFRULESTRING
;
1050 if (*name
== ',' || *name
== ';') {
1059 if ((name
= getrule(name
, &start
)) == NULL
)
1063 if ((name
= getrule(name
, &end
)) == NULL
)
1067 sp
->typecnt
= 2; /* standard time and DST */
1069 ** Two transitions per year, from EPOCH_YEAR to 2037.
1071 sp
->timecnt
= 2 * (2037 - EPOCH_YEAR
+ 1);
1072 if (sp
->timecnt
> TZ_MAX_TIMES
)
1074 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
1075 sp
->ttis
[0].tt_isdst
= 1;
1076 sp
->ttis
[0].tt_abbrind
= stdlen
+ 1;
1077 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
1078 sp
->ttis
[1].tt_isdst
= 0;
1079 sp
->ttis
[1].tt_abbrind
= 0;
1083 for (year
= EPOCH_YEAR
; year
<= 2037; ++year
) {
1084 starttime
= transtime(janfirst
, year
, &start
,
1086 endtime
= transtime(janfirst
, year
, &end
,
1088 if (starttime
> endtime
) {
1090 *typep
++ = 1; /* DST ends */
1092 *typep
++ = 0; /* DST begins */
1095 *typep
++ = 0; /* DST begins */
1097 *typep
++ = 1; /* DST ends */
1099 janfirst
+= year_lengths
[isleap(year
)] *
1103 long theirstdoffset
;
1104 long theirdstoffset
;
1113 ** Initial values of theirstdoffset and theirdstoffset.
1116 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1118 if (!sp
->ttis
[j
].tt_isdst
) {
1120 -sp
->ttis
[j
].tt_gmtoff
;
1125 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1127 if (sp
->ttis
[j
].tt_isdst
) {
1129 -sp
->ttis
[j
].tt_gmtoff
;
1134 ** Initially we're assumed to be in standard time.
1137 theiroffset
= theirstdoffset
;
1139 ** Now juggle transition times and types
1140 ** tracking offsets as you do.
1142 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1144 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1145 if (sp
->ttis
[j
].tt_ttisgmt
) {
1146 /* No adjustment to transition time */
1149 ** If summer time is in effect, and the
1150 ** transition time was not specified as
1151 ** standard time, add the summer time
1152 ** offset to the transition time;
1153 ** otherwise, add the standard time
1154 ** offset to the transition time.
1157 ** Transitions from DST to DDST
1158 ** will effectively disappear since
1159 ** POSIX provides for only one DST
1162 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1163 sp
->ats
[i
] += dstoffset
-
1166 sp
->ats
[i
] += stdoffset
-
1170 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1171 if (sp
->ttis
[j
].tt_isdst
)
1172 theirdstoffset
= theiroffset
;
1173 else theirstdoffset
= theiroffset
;
1176 ** Finally, fill in ttis.
1177 ** ttisstd and ttisgmt need not be handled.
1179 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1180 sp
->ttis
[0].tt_isdst
= FALSE
;
1181 sp
->ttis
[0].tt_abbrind
= 0;
1182 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1183 sp
->ttis
[1].tt_isdst
= TRUE
;
1184 sp
->ttis
[1].tt_abbrind
= stdlen
+ 1;
1189 sp
->typecnt
= 1; /* only standard time */
1191 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1192 sp
->ttis
[0].tt_isdst
= 0;
1193 sp
->ttis
[0].tt_abbrind
= 0;
1195 sp
->charcnt
= stdlen
+ 1;
1197 sp
->charcnt
+= dstlen
+ 1;
1198 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1201 (void) strncpy(cp
, stdname
, stdlen
);
1205 (void) strncpy(cp
, dstname
, dstlen
);
1206 *(cp
+ dstlen
) = '\0';
1213 struct state
* const sp
;
1215 if (tzload(gmt
, sp
) != 0)
1216 (void) tzparse(gmt
, sp
, TRUE
);
1220 tzsetwall_basic(void)
1223 notify_check_tz(&lcl_notify
);
1224 #endif /* NOTIFY_TZ */
1225 #ifdef NOTIFY_TZ_DEBUG
1226 if (lcl_is_set
< 0) {
1227 NOTIFY_TZ_PRINTF("tzsetwall_basic lcl_is_set < 0\n");
1230 NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
1231 #else /* ! NOTIFY_TZ_DEBUG */
1234 #endif /* NOTIFY_TZ_DEBUG */
1238 if (lclptr
== NULL
) {
1239 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1240 if (lclptr
== NULL
) {
1241 settzname(); /* all we can do */
1245 #endif /* defined ALL_STATE */
1246 if (tzload((char *) NULL
, lclptr
) != 0)
1249 notify_register_tz(fullname
, &lcl_notify
);
1250 #endif /* NOTIFY_TZ */
1257 #ifdef NOTIFY_TZ_DEBUG
1258 NOTIFY_TZ_PRINTF("tzsetwall called\n");
1259 #endif /* NOTIFY_TZ_DEBUG */
1260 _MUTEX_LOCK(&lcl_mutex
);
1262 _MUTEX_UNLOCK(&lcl_mutex
);
1265 __private_extern__
void
1270 name
= getenv("TZ");
1277 notify_check_tz(&lcl_notify
);
1278 #endif /* NOTIFY_TZ */
1279 #ifdef NOTIFY_TZ_DEBUG
1280 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0) {
1281 NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname
);
1284 #else /* ! NOTIFY_TZ_DEBUG */
1285 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1287 #endif /* NOTIFY_TZ_DEBUG */
1288 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1290 (void) strcpy(lcl_TZname
, name
);
1293 if (lclptr
== NULL
) {
1294 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1295 if (lclptr
== NULL
) {
1296 settzname(); /* all we can do */
1300 #endif /* defined ALL_STATE */
1301 if (*name
== '\0') {
1303 ** User wants it fast rather than right.
1305 lclptr
->leapcnt
= 0; /* so, we're off a little */
1306 lclptr
->timecnt
= 0;
1307 lclptr
->typecnt
= 0;
1308 lclptr
->ttis
[0].tt_isdst
= 0;
1309 lclptr
->ttis
[0].tt_gmtoff
= 0;
1310 lclptr
->ttis
[0].tt_abbrind
= 0;
1311 (void) strcpy(lclptr
->chars
, gmt
);
1315 #endif /* NOTIFY_TZ */
1316 } else if (tzload(name
, lclptr
) != 0)
1317 if (name
[0] == ':' || tzparse(name
, lclptr
, FALSE
) != 0)
1318 (void) gmtload(lclptr
);
1320 notify_register_tz(fullname
, &lcl_notify
);
1321 #endif /* NOTIFY_TZ */
1328 #ifdef NOTIFY_TZ_DEBUG
1329 NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
1330 #endif /* NOTIFY_TZ_DEBUG */
1331 _MUTEX_LOCK(&lcl_mutex
);
1333 _MUTEX_UNLOCK(&lcl_mutex
);
1337 ** The easy way to behave "as if no library function calls" localtime
1338 ** is to not call it--so we drop its guts into "localsub", which can be
1339 ** freely called. (And no, the PANS doesn't require the above behavior--
1340 ** but it *is* desirable.)
1342 ** The unused offset argument is for the benefit of mktime variants.
1347 __private_extern__
struct tm
*
1348 #else /* !__LP64__ */
1349 __private_extern__
void
1350 #endif /* __LP64__ */
1351 localsub(timep
, offset
, tmp
)
1352 const time_t * const timep
;
1354 struct tm
* const tmp
;
1357 const struct ttinfo
* ttisp
;
1359 const time_t t
= *timep
;
1361 #ifdef NOTIFY_TZ_DEBUG
1362 NOTIFY_TZ_PRINTF("localsub called\n");
1363 #endif /* NOTIFY_TZ_DEBUG */
1368 return gmtsub(timep
, offset
, tmp
);
1369 #else /* !__LP64__ */
1370 gmtsub(timep
, offset
, tmp
);
1372 #endif /* __LP64__ */
1374 #endif /* defined ALL_STATE */
1375 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1377 while (sp
->ttis
[i
].tt_isdst
)
1378 if (++i
>= sp
->typecnt
) {
1383 for (i
= 1; i
< sp
->timecnt
; ++i
)
1386 i
= sp
->types
[i
- 1];
1388 ttisp
= &sp
->ttis
[i
];
1390 ** To get (wrong) behavior that's compatible with System V Release 2.0
1391 ** you'd replace the statement below with
1392 ** t += ttisp->tt_gmtoff;
1393 ** timesub(&t, 0L, sp, tmp);
1396 if (timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
) == NULL
)
1398 #else /* !__LP64__ */
1399 timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1400 #endif /* __LP64__ */
1401 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1402 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1404 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1405 #endif /* defined TM_ZONE */
1408 #endif /* __LP64__ */
1413 const time_t * const timep
;
1415 static pthread_mutex_t localtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1416 static pthread_key_t localtime_key
= -1;
1419 if (__isthreaded
!= 0) {
1420 _pthread_mutex_lock(&localtime_mutex
);
1421 if (localtime_key
== (pthread_key_t
)-1) {
1422 localtime_key
= __LIBC_PTHREAD_KEY_LOCALTIME
;
1423 if (pthread_key_init_np(localtime_key
, free
) < 0) {
1424 _pthread_mutex_unlock(&localtime_mutex
);
1428 _pthread_mutex_unlock(&localtime_mutex
);
1429 p_tm
= _pthread_getspecific(localtime_key
);
1431 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1434 _pthread_setspecific(localtime_key
, p_tm
);
1436 _pthread_mutex_lock(&lcl_mutex
);
1439 p_tm
= localsub(timep
, 0L, p_tm
);
1440 #else /* !__LP64__ */
1441 localsub(timep
, 0L, p_tm
);
1442 #endif /* __LP64__ */
1443 _pthread_mutex_unlock(&lcl_mutex
);
1448 return localsub(timep
, 0L, &tm
);
1449 #else /* !__LP64__ */
1450 localsub(timep
, 0L, &tm
);
1452 #endif /* __LP64__ */
1457 ** Re-entrant version of localtime.
1461 localtime_r(const time_t * const __restrict timep
, struct tm
* __restrict tm
)
1463 _MUTEX_LOCK(&lcl_mutex
);
1466 tm
= localsub(timep
, 0L, tm
);
1467 #else /* !__LP64__ */
1468 localsub(timep
, 0L, tm
);
1469 #endif /* __LP64__ */
1470 _MUTEX_UNLOCK(&lcl_mutex
);
1475 ** gmtsub is to gmtime as localsub is to localtime.
1480 #else /* !__LP64__ */
1482 #endif /* __LP64__ */
1483 gmtsub(timep
, offset
, tmp
)
1484 const time_t * const timep
;
1486 struct tm
* const tmp
;
1488 #ifdef NOTIFY_TZ_DEBUG
1489 NOTIFY_TZ_PRINTF("gmtsub called\n");
1490 #endif /* NOTIFY_TZ_DEBUG */
1491 _MUTEX_LOCK(&gmt_mutex
);
1493 notify_check_tz(&gmt_notify
);
1494 #endif /* NOTIFY_TZ */
1500 #endif /* NOTIFY_TZ */
1501 gmtptr
= (struct state
*) malloc(sizeof *gmtptr
);
1505 #endif /* NOTIFY_TZ */
1506 #endif /* defined ALL_STATE */
1509 notify_register_tz(fullname
, &gmt_notify
);
1511 #endif /* NOTIFY_TZ */
1513 _MUTEX_UNLOCK(&gmt_mutex
);
1515 if(timesub(timep
, offset
, gmtptr
, tmp
) == NULL
)
1517 #else /* !__LP64__ */
1518 timesub(timep
, offset
, gmtptr
, tmp
);
1519 #endif /* __LP64__ */
1522 ** Could get fancy here and deliver something such as
1523 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1524 ** but this is no time for a treasure hunt.
1527 tmp
->TM_ZONE
= wildabbr
;
1531 tmp
->TM_ZONE
= (char *)gmt
;
1532 else tmp
->TM_ZONE
= gmtptr
->chars
;
1533 #endif /* defined ALL_STATE */
1535 tmp
->TM_ZONE
= gmtptr
->chars
;
1536 #endif /* State Farm */
1538 #endif /* defined TM_ZONE */
1541 #endif /* __LP64__ */
1546 const time_t * const timep
;
1548 static pthread_mutex_t gmtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1549 static pthread_key_t gmtime_key
= -1;
1553 if (__isthreaded
!= 0) {
1554 _pthread_mutex_lock(&gmtime_mutex
);
1555 if (gmtime_key
== (pthread_key_t
)-1) {
1556 gmtime_key
= __LIBC_PTHREAD_KEY_GMTIME
;
1557 if (pthread_key_init_np(gmtime_key
, free
) < 0) {
1558 _pthread_mutex_unlock(&gmtime_mutex
);
1562 _pthread_mutex_unlock(&gmtime_mutex
);
1564 * Changed to follow POSIX.1 threads standard, which
1565 * is what BSD currently has.
1567 if ((p_tm
= _pthread_getspecific(gmtime_key
)) == NULL
) {
1568 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1572 _pthread_setspecific(gmtime_key
, p_tm
);
1575 return gmtsub(timep
, 0L, p_tm
);
1576 #else /* !__LP64__ */
1577 gmtsub(timep
, 0L, p_tm
);
1579 #endif /* __LP64__ */
1583 return gmtsub(timep
, 0L, &tm
);
1584 #else /* !__LP64__ */
1585 gmtsub(timep
, 0L, &tm
);
1587 #endif /* __LP64__ */
1592 * Re-entrant version of gmtime.
1597 const time_t * const timep
;
1602 return gmtsub(timep
, 0L, tm
);
1603 #else /* !__LP64__ */
1604 gmtsub(timep
, 0L, tm
);
1606 #endif /* __LP64__ */
1612 offtime(timep
, offset
)
1613 const time_t * const timep
;
1617 return gmtsub(timep
, offset
, &tm
);
1618 #else /* !__LP64__ */
1619 gmtsub(timep
, offset
, &tm
);
1621 #endif /* __LP64__ */
1624 #endif /* defined STD_INSPIRED */
1628 #else /* !__LP64__ */
1630 #endif /* __LP64__ */
1631 timesub(timep
, offset
, sp
, tmp
)
1632 const time_t * const timep
;
1634 const struct state
* const sp
;
1635 struct tm
* const tmp
;
1637 const struct lsinfo
* lp
;
1650 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1651 #endif /* defined ALL_STATE */
1654 #endif /* State Farm */
1657 if (*timep
>= lp
->ls_trans
) {
1658 if (*timep
== lp
->ls_trans
) {
1659 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1660 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1663 sp
->lsis
[i
].ls_trans
==
1664 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1665 sp
->lsis
[i
].ls_corr
==
1666 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1675 days
= *timep
/ SECSPERDAY
;
1676 rem
= *timep
% SECSPERDAY
;
1678 if (*timep
== 0x80000000) {
1680 ** A 3B1 muffs the division on the most negative number.
1685 #endif /* defined mc68k */
1686 rem
+= (offset
- corr
);
1691 while (rem
>= SECSPERDAY
) {
1695 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1696 rem
= rem
% SECSPERHOUR
;
1697 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1699 ** A positive leap second requires a special
1700 ** representation. This uses "... ??:59:60" et seq.
1702 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1703 tmp
->tm_wday
= (int) ((EPOCH_WDAY
+ days
) % DAYSPERWEEK
);
1704 if (tmp
->tm_wday
< 0)
1705 tmp
->tm_wday
+= DAYSPERWEEK
;
1707 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
1708 while (days
< 0 || days
>= (long) year_lengths
[yleap
= isleap(y
)]) {
1711 newy
= y
+ days
/ DAYSPERNYEAR
;
1714 days
-= (newy
- y
) * DAYSPERNYEAR
+
1715 LEAPS_THRU_END_OF(newy
- 1) -
1716 LEAPS_THRU_END_OF(y
- 1);
1721 if (y
< INT_MIN
|| y
> INT_MAX
) {
1726 #else /* !__LP64__ */
1727 tmp
->tm_year
= y
- TM_YEAR_BASE
;
1728 #endif /* __LP64__ */
1729 tmp
->tm_yday
= (int) days
;
1730 ip
= mon_lengths
[yleap
];
1731 for (tmp
->tm_mon
= 0; days
>= (long) ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1732 days
= days
- (long) ip
[tmp
->tm_mon
];
1733 tmp
->tm_mday
= (int) (days
+ 1);
1736 tmp
->TM_GMTOFF
= offset
;
1737 #endif /* defined TM_GMTOFF */
1740 #endif /* __LP64__ */
1745 const time_t * const timep
;
1748 ** Section 4.12.3.2 of X3.159-1989 requires that
1749 ** The ctime function converts the calendar time pointed to by timer
1750 ** to local time in the form of a string. It is equivalent to
1751 ** asctime(localtime(timer))
1755 * In 64-bit, the timep value may produce a time value with a year
1756 * that exceeds 32-bits in size (won't fit in struct tm), so localtime
1759 struct tm
*tm
= localtime(timep
);
1764 #else /* !__LP64__ */
1765 return asctime(localtime(timep
));
1766 #endif /* __LP64__ */
1771 const time_t * const timep
;
1778 * In 64-bit, the timep value may produce a time value with a year
1779 * that exceeds 32-bits in size (won't fit in struct tm), so localtime_r
1782 if (localtime_r(timep
, &tm
) == NULL
)
1784 return asctime_r(&tm
, buf
);
1785 #else /* !__LP64__ */
1786 return asctime_r(localtime_r(timep
, &tm
), buf
);
1787 #endif /* __LP64__ */
1791 ** Adapted from code provided by Robert Elz, who writes:
1792 ** The "best" way to do mktime I think is based on an idea of Bob
1793 ** Kridle's (so its said...) from a long time ago.
1794 ** [kridle@xinet.com as of 1996-01-16.]
1795 ** It does a binary search of the time_t space. Since time_t's are
1796 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1797 ** would still be very reasonable).
1802 #endif /* !defined WRONG */
1805 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1809 increment_overflow(number
, delta
)
1817 return (*number
< number0
) != (delta
< 0);
1821 normalize_overflow(tensptr
, unitsptr
, base
)
1822 int * const tensptr
;
1823 int * const unitsptr
;
1828 tensdelta
= (*unitsptr
>= 0) ?
1829 (*unitsptr
/ base
) :
1830 (-1 - (-1 - *unitsptr
) / base
);
1831 *unitsptr
-= tensdelta
* base
;
1832 return increment_overflow(tensptr
, tensdelta
);
1837 const struct tm
* const atmp
;
1838 const struct tm
* const btmp
;
1842 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
1843 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1844 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1845 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1846 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1847 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1852 time2sub(tmp
, funcp
, offset
, okayp
, do_norm_secs
, unix03
)
1853 struct tm
* const tmp
;
1855 struct tm
*(* const funcp
)(const time_t*, long, struct tm
*);
1856 #else /* !__LP64__ */
1857 void (* const funcp
)(const time_t*, long, struct tm
*);
1858 #endif /* __LP64__ */
1861 const int do_norm_secs
;
1864 const struct state
* sp
;
1871 struct tm yourtm
, mytm
;
1874 #endif /* __LP64__ */
1879 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1883 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1885 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1887 if (normalize_overflow(&yourtm
.tm_year
, &yourtm
.tm_mon
, MONSPERYEAR
))
1890 ** Turn yourtm.tm_year into an actual year number for now.
1891 ** It is converted back to an offset from TM_YEAR_BASE later.
1894 year
= (long)yourtm
.tm_year
+ TM_YEAR_BASE
;
1895 #else /* !__LP64__ */
1896 if (increment_overflow(&yourtm
.tm_year
, TM_YEAR_BASE
))
1898 #endif /* __LP64__ */
1899 while (yourtm
.tm_mday
<= 0) {
1902 il
= year
+ (1 < yourtm
.tm_mon
);
1903 yourtm
.tm_mday
+= year_lengths
[isleap(il
)];
1904 #else /* !__LP64__ */
1905 if (increment_overflow(&yourtm
.tm_year
, -1))
1907 i
= yourtm
.tm_year
+ (1 < yourtm
.tm_mon
);
1908 yourtm
.tm_mday
+= year_lengths
[isleap(i
)];
1909 #endif /* __LP64__ */
1911 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1913 il
= year
+ (1 < yourtm
.tm_mon
);
1914 yourtm
.tm_mday
-= year_lengths
[isleap(il
)];
1916 #else /* !__LP64__ */
1917 i
= yourtm
.tm_year
+ (1 < yourtm
.tm_mon
);
1918 yourtm
.tm_mday
-= year_lengths
[isleap(i
)];
1919 if (increment_overflow(&yourtm
.tm_year
, 1))
1921 #endif /* __LP64__ */
1925 i
= mon_lengths
[isleap(year
)][yourtm
.tm_mon
];
1926 #else /* !__LP64__ */
1927 i
= mon_lengths
[isleap(yourtm
.tm_year
)][yourtm
.tm_mon
];
1928 #endif /* __LP64__ */
1929 if (yourtm
.tm_mday
<= i
)
1931 yourtm
.tm_mday
-= i
;
1932 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1936 #else /* !__LP64__ */
1937 if (increment_overflow(&yourtm
.tm_year
, 1))
1939 #endif /* __LP64__ */
1943 year
-= TM_YEAR_BASE
;
1944 if (year
> INT_MAX
|| year
< INT_MIN
)
1946 yourtm
.tm_year
= year
;
1947 #else /* !__LP64__ */
1948 if (increment_overflow(&yourtm
.tm_year
, -TM_YEAR_BASE
))
1950 #endif /* __LP64__ */
1951 /* Don't go below 1900 for POLA */
1952 if (yourtm
.tm_year
< 0)
1954 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1956 else if (yourtm
.tm_year
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1958 ** We can't set tm_sec to 0, because that might push the
1959 ** time below the minimum representable time.
1960 ** Set tm_sec to 59 instead.
1961 ** This assumes that the minimum representable time is
1962 ** not in the same minute that a leap second was deleted from,
1963 ** which is a safer assumption than using 58 would be.
1965 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1967 saved_seconds
= yourtm
.tm_sec
;
1968 yourtm
.tm_sec
= SECSPERMIN
- 1;
1970 saved_seconds
= yourtm
.tm_sec
;
1974 ** Divide the search space in half
1975 ** (this works whether time_t is signed or unsigned).
1978 /* optimization: see if the value is 31-bit (signed) */
1979 t
= (((time_t) 1) << (TYPE_BIT(int) - 1)) - 1;
1980 bits
= ((*funcp
)(&t
, offset
, &mytm
) == NULL
|| tmcomp(&mytm
, &yourtm
) < 0) ? TYPE_BIT(time_t) - 1 : TYPE_BIT(int) - 1;
1981 #else /* !__LP64__ */
1982 bits
= TYPE_BIT(time_t) - 1;
1983 #endif /* __LP64__ */
1985 ** If we have more than this, we will overflow tm_year for tmcomp().
1986 ** We should really return an error if we cannot represent it.
1991 ** If time_t is signed, then 0 is just above the median,
1992 ** assuming two's complement arithmetic.
1993 ** If time_t is unsigned, then (1 << bits) is just above the median.
1995 t
= TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits
);
1998 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
1999 /* we overflowed, so t is too big */
2003 #else /* !__LP64__ */
2004 (*funcp
)(&t
, offset
, &mytm
);
2005 #endif /* __LP64__ */
2006 dir
= tmcomp(&mytm
, &yourtm
);
2009 #endif /* __LP64__ */
2014 --t
; /* may be needed if new t is minimal */
2016 t
-= ((time_t) 1) << bits
;
2017 else t
+= ((time_t) 1) << bits
;
2020 sp
= (funcp
== localsub
) ? lclptr
: gmtptr
;
2021 if (unix03
&& sp
->typecnt
== 1 && yourtm
.tm_isdst
> 0)
2022 yourtm
.tm_isdst
= 0; /* alternative time does not apply */
2023 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
2026 ** Right time, wrong type.
2027 ** Hunt for right time, right type.
2028 ** It's okay to guess wrong since the guess
2034 #endif /* defined ALL_STATE */
2035 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
2036 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
2038 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
2039 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
2041 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
2042 sp
->ttis
[i
].tt_gmtoff
;
2044 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
2046 #else /* !__LP64__ */
2047 (*funcp
)(&newt
, offset
, &mytm
);
2048 #endif /* __LP64__ */
2049 if (tmcomp(&mytm
, &yourtm
) != 0)
2051 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
2063 newt
= t
+ saved_seconds
;
2064 if ((newt
< t
) != (saved_seconds
< 0))
2068 if ((*funcp
)(&t
, offset
, tmp
) == NULL
)
2070 #else /* !__LP64__ */
2071 (*funcp
)(&t
, offset
, tmp
);
2072 #endif /* __LP64__ */
2078 time2(tmp
, funcp
, offset
, okayp
, unix03
)
2079 struct tm
* const tmp
;
2081 struct tm
*(* const funcp
)(const time_t*, long, struct tm
*);
2082 #else /* !__LP64__ */
2083 void (* const funcp
)(const time_t*, long, struct tm
*);
2084 #endif /* __LP64__ */
2092 ** First try without normalization of seconds
2093 ** (in case tm_sec contains a value associated with a leap second).
2094 ** If that fails, try with normalization of seconds.
2096 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
, unix03
);
2097 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
, unix03
);
2100 __private_extern__
time_t
2101 time1(tmp
, funcp
, offset
, unix03
)
2102 struct tm
* const tmp
;
2104 struct tm
*(* const funcp
)(const time_t *, long, struct tm
*);
2105 #else /* !__LP64__ */
2106 void (* const funcp
)(const time_t *, long, struct tm
*);
2107 #endif /* __LP64__ */
2112 const struct state
* sp
;
2114 int sameind
, otherind
;
2117 int seen
[TZ_MAX_TYPES
];
2118 int types
[TZ_MAX_TYPES
];
2121 if (tmp
->tm_isdst
> 1)
2123 t
= time2(tmp
, funcp
, offset
, &okay
, unix03
);
2126 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
2130 if (tmp
->tm_isdst
< 0)
2131 tmp
->tm_isdst
= 0; /* reset to std and try again */
2132 #endif /* defined PCTS */
2134 if (okay
|| tmp
->tm_isdst
< 0)
2136 #endif /* !defined PCTS */
2138 ** We're supposed to assume that somebody took a time of one type
2139 ** and did some math on it that yielded a "struct tm" that's bad.
2140 ** We try to divine the type they started from and adjust to the
2143 sp
= (funcp
== localsub
) ? lclptr
: gmtptr
;
2147 #endif /* defined ALL_STATE */
2148 for (i
= 0; i
< sp
->typecnt
; ++i
)
2151 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
2152 if (!seen
[sp
->types
[i
]]) {
2153 seen
[sp
->types
[i
]] = TRUE
;
2154 types
[nseen
++] = sp
->types
[i
];
2156 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2157 samei
= types
[sameind
];
2158 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2160 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2161 otheri
= types
[otherind
];
2162 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
2164 tmp
->tm_sec
+= sp
->ttis
[otheri
].tt_gmtoff
-
2165 sp
->ttis
[samei
].tt_gmtoff
;
2166 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2167 t
= time2(tmp
, funcp
, offset
, &okay
, unix03
);
2170 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
2171 sp
->ttis
[samei
].tt_gmtoff
;
2172 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2177 #else /* BUILDING_VARIANT */
2178 __private_extern__ pthread_mutex_t lcl_mutex
;
2179 #endif /* BUILDING_VARIANT */
2183 struct tm
* const tmp
;
2185 time_t mktime_return_value
;
2187 _MUTEX_LOCK(&lcl_mutex
);
2189 mktime_return_value
= time1(tmp
, localsub
, 0L, __DARWIN_UNIX03
);
2190 _MUTEX_UNLOCK(&lcl_mutex
);
2192 return(mktime_return_value
);
2195 #if !BUILDING_VARIANT
2200 struct tm
* const tmp
;
2202 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2208 struct tm
* const tmp
;
2211 return time1(tmp
, gmtsub
, 0L, __DARWIN_UNIX03
);
2215 timeoff(tmp
, offset
)
2216 struct tm
* const tmp
;
2220 return time1(tmp
, gmtsub
, offset
, __DARWIN_UNIX03
);
2223 #endif /* defined STD_INSPIRED */
2228 ** The following is supplied for compatibility with
2229 ** previous versions of the CMUCS runtime library.
2234 struct tm
* const tmp
;
2236 const time_t t
= mktime(tmp
);
2243 #endif /* defined CMUCS */
2246 ** XXX--is the below the right way to conditionalize??
2252 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2253 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2254 ** is not the case if we are accounting for leap seconds.
2255 ** So, we provide the following conversion routines for use
2256 ** when exchanging timestamps with POSIX conforming systems.
2271 if (*timep
>= lp
->ls_trans
)
2282 return t
- leapcorr(&t
);
2294 ** For a positive leap second hit, the result
2295 ** is not unique. For a negative leap second
2296 ** hit, the corresponding time doesn't exist,
2297 ** so we return an adjacent second.
2299 x
= t
+ leapcorr(&t
);
2300 y
= x
- leapcorr(&x
);
2304 y
= x
- leapcorr(&x
);
2311 y
= x
- leapcorr(&x
);
2319 #endif /* defined STD_INSPIRED */
2320 #endif /* !BUILDING_VARIANT */