2 ** This file is in the public domain, so clarified as of
3 ** June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
9 static char elsieid
[] __unused
= "@(#)localtime.c 7.57";
10 #endif /* !defined NOID */
11 #endif /* !defined lint */
12 __FBSDID("$FreeBSD: src/lib/libc/stdtime/localtime.c,v 1.36 2003/02/16 17:29:11 nectar 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>
28 #include "un-namespace.h"
32 #include "libc_private.h"
34 #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
35 #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
38 ** SunOS 4.1.1 headers lack O_BINARY.
42 #define OPEN_MODE (O_RDONLY | O_BINARY)
43 #endif /* defined O_BINARY */
45 #define OPEN_MODE O_RDONLY
46 #endif /* !defined O_BINARY */
50 ** Someone might make incorrect use of a time zone abbreviation:
51 ** 1. They might reference tzname[0] before calling tzset (explicitly
53 ** 2. They might reference tzname[1] before calling tzset (explicitly
55 ** 3. They might reference tzname[1] after setting to a time zone
56 ** in which Daylight Saving Time is never observed.
57 ** 4. They might reference tzname[0] after setting to a time zone
58 ** in which Standard Time is never observed.
59 ** 5. They might reference tm.TM_ZONE after calling offtime.
60 ** What's best to do in the above cases is open to debate;
61 ** for now, we just set things up so that in any of the five cases
62 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
63 ** string "tzname[0] used before set", and similarly for the other cases.
64 ** And another: initialize tzname[0] to "ERA", with an explanation in the
65 ** manual page of what this "time zone abbreviation" means (doing this so
66 ** that tzname[0] has the "normal" length of three characters).
69 #endif /* !defined WILDABBR */
71 static char wildabbr
[] = "WILDABBR";
73 static const char gmt
[] = "GMT";
75 struct ttinfo
{ /* time type information */
76 long tt_gmtoff
; /* GMT offset in seconds */
77 int tt_isdst
; /* used to set tm_isdst */
78 int tt_abbrind
; /* abbreviation list index */
79 int tt_ttisstd
; /* TRUE if transition is std time */
80 int tt_ttisgmt
; /* TRUE if transition is GMT */
83 struct lsinfo
{ /* leap second information */
84 time_t ls_trans
; /* transition time */
85 long ls_corr
; /* correction to apply */
88 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
91 #define MY_TZNAME_MAX TZNAME_MAX
92 #endif /* defined TZNAME_MAX */
94 #define MY_TZNAME_MAX 255
95 #endif /* !defined TZNAME_MAX */
102 time_t ats
[TZ_MAX_TIMES
];
103 unsigned char types
[TZ_MAX_TIMES
];
104 struct ttinfo ttis
[TZ_MAX_TYPES
];
105 char chars
[BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
106 (2 * (MY_TZNAME_MAX
+ 1)))];
107 struct lsinfo lsis
[TZ_MAX_LEAPS
];
111 int r_type
; /* type of rule--see below */
112 int r_day
; /* day number of rule */
113 int r_week
; /* week number of rule */
114 int r_mon
; /* month number of rule */
115 long r_time
; /* transition time of rule */
118 #define JULIAN_DAY 0 /* Jn - Julian day */
119 #define DAY_OF_YEAR 1 /* n - day of year */
120 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
123 ** Prototypes for static functions.
126 static long detzcode(const char * codep
);
127 static const char * getzname(const char * strp
);
128 static const char * getnum(const char * strp
, int * nump
, int min
,
130 static const char * getsecs(const char * strp
, long * secsp
);
131 static const char * getoffset(const char * strp
, long * offsetp
);
132 static const char * getrule(const char * strp
, struct rule
* rulep
);
133 static void gmtload(struct state
* sp
);
134 static void gmtsub(const time_t * timep
, long offset
,
136 static void localsub(const time_t * timep
, long offset
,
138 static int increment_overflow(int * number
, int delta
);
139 static int normalize_overflow(int * tensptr
, int * unitsptr
,
141 static void settzname(void);
142 static time_t time1(struct tm
* tmp
,
143 void(*funcp
) (const time_t *,
146 static time_t time2(struct tm
*tmp
,
147 void(*funcp
) (const time_t *,
149 long offset
, int * okayp
);
150 static void timesub(const time_t * timep
, long offset
,
151 const struct state
* sp
, struct tm
* tmp
);
152 static int tmcomp(const struct tm
* atmp
,
153 const struct tm
* btmp
);
154 static time_t transtime(time_t janfirst
, int year
,
155 const struct rule
* rulep
, long offset
);
156 static int tzload(const char * name
, struct state
* sp
);
157 static int tzparse(const char * name
, struct state
* sp
,
161 static struct state
* lclptr
;
162 static struct state
* gmtptr
;
163 #endif /* defined ALL_STATE */
166 static struct state lclmem
;
167 static struct state gmtmem
;
168 #define lclptr (&lclmem)
169 #define gmtptr (&gmtmem)
170 #endif /* State Farm */
172 #ifndef TZ_STRLEN_MAX
173 #define TZ_STRLEN_MAX 255
174 #endif /* !defined TZ_STRLEN_MAX */
176 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
177 static int lcl_is_set
;
178 static int gmt_is_set
;
179 static pthread_mutex_t lcl_mutex
= PTHREAD_MUTEX_INITIALIZER
;
180 static pthread_mutex_t gmt_mutex
= PTHREAD_MUTEX_INITIALIZER
;
188 ** Section 4.12.3 of X3.159-1989 requires that
189 ** Except for the strftime function, these functions [asctime,
190 ** ctime, gmtime, localtime] return values in one of two static
191 ** objects: a broken-down time structure and an array of char.
192 ** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
200 #endif /* defined USG_COMPAT */
204 #endif /* defined ALTZONE */
208 const char * const codep
;
213 result
= (codep
[0] & 0x80) ? ~0L : 0L;
214 for (i
= 0; i
< 4; ++i
)
215 result
= (result
<< 8) | (codep
[i
] & 0xff);
222 struct state
* sp
= lclptr
;
225 tzname
[0] = wildabbr
;
226 tzname
[1] = wildabbr
;
230 #endif /* defined USG_COMPAT */
233 #endif /* defined ALTZONE */
236 tzname
[0] = tzname
[1] = gmt
;
239 #endif /* defined ALL_STATE */
240 for (i
= 0; i
< sp
->typecnt
; ++i
) {
241 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
243 tzname
[ttisp
->tt_isdst
] =
244 &sp
->chars
[ttisp
->tt_abbrind
];
248 if (i
== 0 || !ttisp
->tt_isdst
)
249 timezone
= -(ttisp
->tt_gmtoff
);
250 #endif /* defined USG_COMPAT */
252 if (i
== 0 || ttisp
->tt_isdst
)
253 altzone
= -(ttisp
->tt_gmtoff
);
254 #endif /* defined ALTZONE */
257 ** And to get the latest zone names into tzname. . .
259 for (i
= 0; i
< sp
->timecnt
; ++i
) {
260 const struct ttinfo
* const ttisp
=
264 tzname
[ttisp
->tt_isdst
] =
265 &sp
->chars
[ttisp
->tt_abbrind
];
272 struct state
* const sp
;
278 /* XXX The following is from OpenBSD, and I'm not sure it is correct */
279 if (name
!= NULL
&& issetugid() != 0)
280 if ((name
[0] == ':' && name
[1] == '/') ||
281 name
[0] == '/' || strchr(name
, '.'))
283 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
289 ** Section 4.9.1 of the C standard says that
290 ** "FILENAME_MAX expands to an integral constant expression
291 ** that is the size needed for an array of char large enough
292 ** to hold the longest file name string that the implementation
293 ** guarantees can be opened."
295 char fullname
[FILENAME_MAX
+ 1];
299 doaccess
= name
[0] == '/';
301 if ((p
= TZDIR
) == NULL
)
303 if ((strlen(p
) + 1 + strlen(name
) + 1) >= sizeof fullname
)
305 (void) strcpy(fullname
, p
);
306 (void) strcat(fullname
, "/");
307 (void) strcat(fullname
, name
);
309 ** Set doaccess if '.' (as in "../") shows up in name.
311 if (strchr(name
, '.') != NULL
)
315 if (doaccess
&& access(name
, R_OK
) != 0)
317 if ((fid
= _open(name
, OPEN_MODE
)) == -1)
319 if ((_fstat(fid
, &stab
) < 0) || !S_ISREG(stab
.st_mode
)) {
325 struct tzhead
* tzhp
;
326 char buf
[sizeof *sp
+ sizeof *tzhp
];
330 i
= _read(fid
, buf
, sizeof buf
);
331 if (_close(fid
) != 0)
334 p
+= (sizeof tzhp
->tzh_magic
) + (sizeof tzhp
->tzh_reserved
);
335 ttisstdcnt
= (int) detzcode(p
);
337 ttisgmtcnt
= (int) detzcode(p
);
339 sp
->leapcnt
= (int) detzcode(p
);
341 sp
->timecnt
= (int) detzcode(p
);
343 sp
->typecnt
= (int) detzcode(p
);
345 sp
->charcnt
= (int) detzcode(p
);
347 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
348 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
349 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
350 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
351 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
352 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
354 if (i
- (p
- buf
) < sp
->timecnt
* 4 + /* ats */
355 sp
->timecnt
+ /* types */
356 sp
->typecnt
* (4 + 2) + /* ttinfos */
357 sp
->charcnt
+ /* chars */
358 sp
->leapcnt
* (4 + 4) + /* lsinfos */
359 ttisstdcnt
+ /* ttisstds */
360 ttisgmtcnt
) /* ttisgmts */
362 for (i
= 0; i
< sp
->timecnt
; ++i
) {
363 sp
->ats
[i
] = detzcode(p
);
366 for (i
= 0; i
< sp
->timecnt
; ++i
) {
367 sp
->types
[i
] = (unsigned char) *p
++;
368 if (sp
->types
[i
] >= sp
->typecnt
)
371 for (i
= 0; i
< sp
->typecnt
; ++i
) {
372 struct ttinfo
* ttisp
;
374 ttisp
= &sp
->ttis
[i
];
375 ttisp
->tt_gmtoff
= detzcode(p
);
377 ttisp
->tt_isdst
= (unsigned char) *p
++;
378 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
380 ttisp
->tt_abbrind
= (unsigned char) *p
++;
381 if (ttisp
->tt_abbrind
< 0 ||
382 ttisp
->tt_abbrind
> sp
->charcnt
)
385 for (i
= 0; i
< sp
->charcnt
; ++i
)
387 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
388 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
389 struct lsinfo
* lsisp
;
391 lsisp
= &sp
->lsis
[i
];
392 lsisp
->ls_trans
= detzcode(p
);
394 lsisp
->ls_corr
= detzcode(p
);
397 for (i
= 0; i
< sp
->typecnt
; ++i
) {
398 struct ttinfo
* ttisp
;
400 ttisp
= &sp
->ttis
[i
];
402 ttisp
->tt_ttisstd
= FALSE
;
404 ttisp
->tt_ttisstd
= *p
++;
405 if (ttisp
->tt_ttisstd
!= TRUE
&&
406 ttisp
->tt_ttisstd
!= FALSE
)
410 for (i
= 0; i
< sp
->typecnt
; ++i
) {
411 struct ttinfo
* ttisp
;
413 ttisp
= &sp
->ttis
[i
];
415 ttisp
->tt_ttisgmt
= FALSE
;
417 ttisp
->tt_ttisgmt
= *p
++;
418 if (ttisp
->tt_ttisgmt
!= TRUE
&&
419 ttisp
->tt_ttisgmt
!= FALSE
)
427 static const int mon_lengths
[2][MONSPERYEAR
] = {
428 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
429 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
432 static const int year_lengths
[2] = {
433 DAYSPERNYEAR
, DAYSPERLYEAR
437 ** Given a pointer into a time zone string, scan until a character that is not
438 ** a valid character in a zone name is found. Return a pointer to that
448 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
455 ** Given a pointer into a time zone string, extract a number from that string.
456 ** Check that the number is within a specified range; if it is not, return
458 ** Otherwise, return a pointer to the first character not part of the number.
462 getnum(strp
, nump
, min
, max
)
471 if (strp
== NULL
|| !is_digit(c
= *strp
))
475 num
= num
* 10 + (c
- '0');
477 return NULL
; /* illegal value */
479 } while (is_digit(c
));
481 return NULL
; /* illegal value */
487 ** Given a pointer into a time zone string, extract a number of seconds,
488 ** in hh[:mm[:ss]] form, from the string.
489 ** If any error occurs, return NULL.
490 ** Otherwise, return a pointer to the first character not part of the number
502 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
503 ** "M10.4.6/26", which does not conform to Posix,
504 ** but which specifies the equivalent of
505 ** ``02:00 on the first Sunday on or after 23 Oct''.
507 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
510 *secsp
= num
* (long) SECSPERHOUR
;
513 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
516 *secsp
+= num
* SECSPERMIN
;
519 /* `SECSPERMIN' allows for leap seconds. */
520 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
530 ** Given a pointer into a time zone string, extract an offset, in
531 ** [+-]hh[:mm[:ss]] form, from the string.
532 ** If any error occurs, return NULL.
533 ** Otherwise, return a pointer to the first character not part of the time.
537 getoffset(strp
, offsetp
)
539 long * const offsetp
;
546 } else if (*strp
== '+')
548 strp
= getsecs(strp
, offsetp
);
550 return NULL
; /* illegal time */
552 *offsetp
= -*offsetp
;
557 ** Given a pointer into a time zone string, extract a rule in the form
558 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
559 ** If a valid rule is not found, return NULL.
560 ** Otherwise, return a pointer to the first character not part of the rule.
566 struct rule
* const rulep
;
572 rulep
->r_type
= JULIAN_DAY
;
574 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
575 } else if (*strp
== 'M') {
579 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
581 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
586 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
591 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
592 } else if (is_digit(*strp
)) {
596 rulep
->r_type
= DAY_OF_YEAR
;
597 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
598 } else return NULL
; /* invalid format */
606 strp
= getsecs(strp
, &rulep
->r_time
);
607 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
612 ** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
613 ** year, a rule, and the offset from GMT at the time that rule takes effect,
614 ** calculate the Epoch-relative time that rule takes effect.
618 transtime(janfirst
, year
, rulep
, offset
)
619 const time_t janfirst
;
621 const struct rule
* const rulep
;
627 int d
, m1
, yy0
, yy1
, yy2
, dow
;
630 leapyear
= isleap(year
);
631 switch (rulep
->r_type
) {
635 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
637 ** In non-leap years, or if the day number is 59 or less, just
638 ** add SECSPERDAY times the day number-1 to the time of
639 ** January 1, midnight, to get the day.
641 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
642 if (leapyear
&& rulep
->r_day
>= 60)
649 ** Just add SECSPERDAY times the day number to the time of
650 ** January 1, midnight, to get the day.
652 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
655 case MONTH_NTH_DAY_OF_WEEK
:
657 ** Mm.n.d - nth "dth day" of month m.
660 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
661 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
664 ** Use Zeller's Congruence to get day-of-week of first day of
667 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
668 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
671 dow
= ((26 * m1
- 2) / 10 +
672 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
677 ** "dow" is the day-of-week of the first day of the month. Get
678 ** the day-of-month (zero-origin) of the first "dow" day of the
681 d
= rulep
->r_day
- dow
;
684 for (i
= 1; i
< rulep
->r_week
; ++i
) {
685 if (d
+ DAYSPERWEEK
>=
686 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
692 ** "d" is the day-of-month (zero-origin) of the day we want.
694 value
+= d
* SECSPERDAY
;
699 ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
700 ** question. To get the Epoch-relative time of the specified local
701 ** time on that day, add the transition time and the current offset
704 return value
+ rulep
->r_time
+ offset
;
708 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
713 tzparse(name
, sp
, lastditch
)
715 struct state
* const sp
;
718 const char * stdname
;
719 const char * dstname
;
725 unsigned char * typep
;
732 stdlen
= strlen(name
); /* length of standard zone name */
734 if (stdlen
>= sizeof sp
->chars
)
735 stdlen
= (sizeof sp
->chars
) - 1;
738 name
= getzname(name
);
739 stdlen
= name
- stdname
;
743 return -1; /* was "stdoffset = 0;" */
745 name
= getoffset(name
, &stdoffset
);
750 load_result
= tzload(TZDEFRULES
, sp
);
751 if (load_result
!= 0)
752 sp
->leapcnt
= 0; /* so, we're off a little */
755 name
= getzname(name
);
756 dstlen
= name
- dstname
; /* length of DST zone name */
759 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
760 name
= getoffset(name
, &dstoffset
);
763 } else dstoffset
= stdoffset
- SECSPERHOUR
;
764 if (*name
== ',' || *name
== ';') {
773 if ((name
= getrule(name
, &start
)) == NULL
)
777 if ((name
= getrule(name
, &end
)) == NULL
)
781 sp
->typecnt
= 2; /* standard time and DST */
783 ** Two transitions per year, from EPOCH_YEAR to 2037.
785 sp
->timecnt
= 2 * (2037 - EPOCH_YEAR
+ 1);
786 if (sp
->timecnt
> TZ_MAX_TIMES
)
788 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
789 sp
->ttis
[0].tt_isdst
= 1;
790 sp
->ttis
[0].tt_abbrind
= stdlen
+ 1;
791 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
792 sp
->ttis
[1].tt_isdst
= 0;
793 sp
->ttis
[1].tt_abbrind
= 0;
797 for (year
= EPOCH_YEAR
; year
<= 2037; ++year
) {
798 starttime
= transtime(janfirst
, year
, &start
,
800 endtime
= transtime(janfirst
, year
, &end
,
802 if (starttime
> endtime
) {
804 *typep
++ = 1; /* DST ends */
806 *typep
++ = 0; /* DST begins */
809 *typep
++ = 0; /* DST begins */
811 *typep
++ = 1; /* DST ends */
813 janfirst
+= year_lengths
[isleap(year
)] *
826 if (load_result
!= 0)
829 ** Initial values of theirstdoffset and theirdstoffset.
832 for (i
= 0; i
< sp
->timecnt
; ++i
) {
834 if (!sp
->ttis
[j
].tt_isdst
) {
836 -sp
->ttis
[j
].tt_gmtoff
;
841 for (i
= 0; i
< sp
->timecnt
; ++i
) {
843 if (sp
->ttis
[j
].tt_isdst
) {
845 -sp
->ttis
[j
].tt_gmtoff
;
850 ** Initially we're assumed to be in standard time.
853 theiroffset
= theirstdoffset
;
855 ** Now juggle transition times and types
856 ** tracking offsets as you do.
858 for (i
= 0; i
< sp
->timecnt
; ++i
) {
860 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
861 if (sp
->ttis
[j
].tt_ttisgmt
) {
862 /* No adjustment to transition time */
865 ** If summer time is in effect, and the
866 ** transition time was not specified as
867 ** standard time, add the summer time
868 ** offset to the transition time;
869 ** otherwise, add the standard time
870 ** offset to the transition time.
873 ** Transitions from DST to DDST
874 ** will effectively disappear since
875 ** POSIX provides for only one DST
878 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
879 sp
->ats
[i
] += dstoffset
-
882 sp
->ats
[i
] += stdoffset
-
886 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
887 if (sp
->ttis
[j
].tt_isdst
)
888 theirdstoffset
= theiroffset
;
889 else theirstdoffset
= theiroffset
;
892 ** Finally, fill in ttis.
893 ** ttisstd and ttisgmt need not be handled.
895 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
896 sp
->ttis
[0].tt_isdst
= FALSE
;
897 sp
->ttis
[0].tt_abbrind
= 0;
898 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
899 sp
->ttis
[1].tt_isdst
= TRUE
;
900 sp
->ttis
[1].tt_abbrind
= stdlen
+ 1;
904 sp
->typecnt
= 1; /* only standard time */
906 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
907 sp
->ttis
[0].tt_isdst
= 0;
908 sp
->ttis
[0].tt_abbrind
= 0;
910 sp
->charcnt
= stdlen
+ 1;
912 sp
->charcnt
+= dstlen
+ 1;
913 if (sp
->charcnt
> sizeof sp
->chars
)
916 (void) strncpy(cp
, stdname
, stdlen
);
920 (void) strncpy(cp
, dstname
, dstlen
);
921 *(cp
+ dstlen
) = '\0';
928 struct state
* const sp
;
930 if (tzload(gmt
, sp
) != 0)
931 (void) tzparse(gmt
, sp
, TRUE
);
935 tzsetwall_basic(void)
942 if (lclptr
== NULL
) {
943 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
944 if (lclptr
== NULL
) {
945 settzname(); /* all we can do */
949 #endif /* defined ALL_STATE */
950 if (tzload((char *) NULL
, lclptr
) != 0)
958 _MUTEX_LOCK(&lcl_mutex
);
960 _MUTEX_UNLOCK(&lcl_mutex
);
974 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
976 lcl_is_set
= (strlen(name
) < sizeof(lcl_TZname
));
978 (void) strcpy(lcl_TZname
, name
);
981 if (lclptr
== NULL
) {
982 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
983 if (lclptr
== NULL
) {
984 settzname(); /* all we can do */
988 #endif /* defined ALL_STATE */
991 ** User wants it fast rather than right.
993 lclptr
->leapcnt
= 0; /* so, we're off a little */
995 lclptr
->ttis
[0].tt_gmtoff
= 0;
996 lclptr
->ttis
[0].tt_abbrind
= 0;
997 (void) strcpy(lclptr
->chars
, gmt
);
998 } else if (tzload(name
, lclptr
) != 0)
999 if (name
[0] == ':' || tzparse(name
, lclptr
, FALSE
) != 0)
1000 (void) gmtload(lclptr
);
1007 _MUTEX_LOCK(&lcl_mutex
);
1009 _MUTEX_UNLOCK(&lcl_mutex
);
1013 ** The easy way to behave "as if no library function calls" localtime
1014 ** is to not call it--so we drop its guts into "localsub", which can be
1015 ** freely called. (And no, the PANS doesn't require the above behavior--
1016 ** but it *is* desirable.)
1018 ** The unused offset argument is for the benefit of mktime variants.
1023 localsub(timep
, offset
, tmp
)
1024 const time_t * const timep
;
1026 struct tm
* const tmp
;
1029 const struct ttinfo
* ttisp
;
1031 const time_t t
= *timep
;
1036 gmtsub(timep
, offset
, tmp
);
1039 #endif /* defined ALL_STATE */
1040 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1042 while (sp
->ttis
[i
].tt_isdst
)
1043 if (++i
>= sp
->typecnt
) {
1048 for (i
= 1; i
< sp
->timecnt
; ++i
)
1051 i
= sp
->types
[i
- 1];
1053 ttisp
= &sp
->ttis
[i
];
1055 ** To get (wrong) behavior that's compatible with System V Release 2.0
1056 ** you'd replace the statement below with
1057 ** t += ttisp->tt_gmtoff;
1058 ** timesub(&t, 0L, sp, tmp);
1060 timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1061 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1062 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1064 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1065 #endif /* defined TM_ZONE */
1069 localtime_r(timep
, p_tm
)
1070 const time_t * const timep
;
1073 _MUTEX_LOCK(&lcl_mutex
);
1075 localsub(timep
, 0L, p_tm
);
1076 _MUTEX_UNLOCK(&lcl_mutex
);
1082 const time_t * const timep
;
1084 static pthread_mutex_t localtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1085 static pthread_key_t localtime_key
= -1;
1088 if (__isthreaded
!= 0) {
1089 _pthread_mutex_lock(&localtime_mutex
);
1090 if (localtime_key
< 0) {
1091 if (_pthread_key_create(&localtime_key
, free
) < 0) {
1092 _pthread_mutex_unlock(&localtime_mutex
);
1096 _pthread_mutex_unlock(&localtime_mutex
);
1097 p_tm
= _pthread_getspecific(localtime_key
);
1099 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1102 _pthread_setspecific(localtime_key
, p_tm
);
1104 _pthread_mutex_lock(&lcl_mutex
);
1106 localsub(timep
, 0L, p_tm
);
1107 _pthread_mutex_unlock(&lcl_mutex
);
1111 localsub(timep
, 0L, &tm
);
1117 ** gmtsub is to gmtime as localsub is to localtime.
1121 gmtsub(timep
, offset
, tmp
)
1122 const time_t * const timep
;
1124 struct tm
* const tmp
;
1126 _MUTEX_LOCK(&gmt_mutex
);
1130 gmtptr
= (struct state
*) malloc(sizeof *gmtptr
);
1132 #endif /* defined ALL_STATE */
1135 _MUTEX_UNLOCK(&gmt_mutex
);
1136 timesub(timep
, offset
, gmtptr
, tmp
);
1139 ** Could get fancy here and deliver something such as
1140 ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
1141 ** but this is no time for a treasure hunt.
1144 tmp
->TM_ZONE
= wildabbr
;
1149 else tmp
->TM_ZONE
= gmtptr
->chars
;
1150 #endif /* defined ALL_STATE */
1152 tmp
->TM_ZONE
= gmtptr
->chars
;
1153 #endif /* State Farm */
1155 #endif /* defined TM_ZONE */
1160 const time_t * const timep
;
1162 static pthread_mutex_t gmtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1163 static pthread_key_t gmtime_key
= -1;
1166 if (__isthreaded
!= 0) {
1167 _pthread_mutex_lock(&gmtime_mutex
);
1168 if (gmtime_key
< 0) {
1169 if (_pthread_key_create(&gmtime_key
, free
) < 0) {
1170 _pthread_mutex_unlock(&gmtime_mutex
);
1174 _pthread_mutex_unlock(&gmtime_mutex
);
1176 * Changed to follow POSIX.1 threads standard, which
1177 * is what BSD currently has.
1179 if ((p_tm
= _pthread_getspecific(gmtime_key
)) == NULL
) {
1180 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1184 _pthread_setspecific(gmtime_key
, p_tm
);
1186 gmtsub(timep
, 0L, p_tm
);
1190 gmtsub(timep
, 0L, &tm
);
1196 gmtime_r(const time_t * timep
, struct tm
* tm
)
1198 gmtsub(timep
, 0L, tm
);
1205 offtime(timep
, offset
)
1206 const time_t * const timep
;
1209 gmtsub(timep
, offset
, &tm
);
1213 #endif /* defined STD_INSPIRED */
1216 timesub(timep
, offset
, sp
, tmp
)
1217 const time_t * const timep
;
1219 const struct state
* const sp
;
1220 struct tm
* const tmp
;
1222 const struct lsinfo
* lp
;
1235 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1236 #endif /* defined ALL_STATE */
1239 #endif /* State Farm */
1242 if (*timep
>= lp
->ls_trans
) {
1243 if (*timep
== lp
->ls_trans
) {
1244 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1245 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1248 sp
->lsis
[i
].ls_trans
==
1249 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1250 sp
->lsis
[i
].ls_corr
==
1251 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1260 days
= *timep
/ SECSPERDAY
;
1261 rem
= *timep
% SECSPERDAY
;
1263 if (*timep
== 0x80000000) {
1265 ** A 3B1 muffs the division on the most negative number.
1270 #endif /* defined mc68k */
1271 rem
+= (offset
- corr
);
1276 while (rem
>= SECSPERDAY
) {
1280 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1281 rem
= rem
% SECSPERHOUR
;
1282 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1284 ** A positive leap second requires a special
1285 ** representation. This uses "... ??:59:60" et seq.
1287 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1288 tmp
->tm_wday
= (int) ((EPOCH_WDAY
+ days
) % DAYSPERWEEK
);
1289 if (tmp
->tm_wday
< 0)
1290 tmp
->tm_wday
+= DAYSPERWEEK
;
1292 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
1293 while (days
< 0 || days
>= (long) year_lengths
[yleap
= isleap(y
)]) {
1296 newy
= y
+ days
/ DAYSPERNYEAR
;
1299 days
-= (newy
- y
) * DAYSPERNYEAR
+
1300 LEAPS_THRU_END_OF(newy
- 1) -
1301 LEAPS_THRU_END_OF(y
- 1);
1304 tmp
->tm_year
= y
- TM_YEAR_BASE
;
1305 tmp
->tm_yday
= (int) days
;
1306 ip
= mon_lengths
[yleap
];
1307 for (tmp
->tm_mon
= 0; days
>= (long) ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1308 days
= days
- (long) ip
[tmp
->tm_mon
];
1309 tmp
->tm_mday
= (int) (days
+ 1);
1312 tmp
->TM_GMTOFF
= offset
;
1313 #endif /* defined TM_GMTOFF */
1318 const time_t * const timep
;
1321 ** Section 4.12.3.2 of X3.159-1989 requires that
1322 ** The ctime funciton converts the calendar time pointed to by timer
1323 ** to local time in the form of a string. It is equivalent to
1324 ** asctime(localtime(timer))
1326 return asctime(localtime(timep
));
1331 const time_t * const timep
;
1335 return asctime_r(localtime_r(timep
, &tm
), buf
);
1339 ** Adapted from code provided by Robert Elz, who writes:
1340 ** The "best" way to do mktime I think is based on an idea of Bob
1341 ** Kridle's (so its said...) from a long time ago.
1342 ** [kridle@xinet.com as of 1996-01-16.]
1343 ** It does a binary search of the time_t space. Since time_t's are
1344 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1345 ** would still be very reasonable).
1350 #endif /* !defined WRONG */
1353 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1357 increment_overflow(number
, delta
)
1365 return (*number
< number0
) != (delta
< 0);
1369 normalize_overflow(tensptr
, unitsptr
, base
)
1370 int * const tensptr
;
1371 int * const unitsptr
;
1376 tensdelta
= (*unitsptr
>= 0) ?
1377 (*unitsptr
/ base
) :
1378 (-1 - (-1 - *unitsptr
) / base
);
1379 *unitsptr
-= tensdelta
* base
;
1380 return increment_overflow(tensptr
, tensdelta
);
1385 const struct tm
* const atmp
;
1386 const struct tm
* const btmp
;
1390 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
1391 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1392 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1393 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1394 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1395 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1400 time2(tmp
, funcp
, offset
, okayp
)
1401 struct tm
* const tmp
;
1402 void (* const funcp
)(const time_t*, long, struct tm
*);
1406 const struct state
* sp
;
1413 struct tm yourtm
, mytm
;
1417 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1419 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1421 if (normalize_overflow(&yourtm
.tm_year
, &yourtm
.tm_mon
, MONSPERYEAR
))
1424 ** Turn yourtm.tm_year into an actual year number for now.
1425 ** It is converted back to an offset from TM_YEAR_BASE later.
1427 if (increment_overflow(&yourtm
.tm_year
, TM_YEAR_BASE
))
1429 while (yourtm
.tm_mday
<= 0) {
1430 if (increment_overflow(&yourtm
.tm_year
, -1))
1432 i
= yourtm
.tm_year
+ (1 < yourtm
.tm_mon
);
1433 yourtm
.tm_mday
+= year_lengths
[isleap(i
)];
1435 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1436 i
= yourtm
.tm_year
+ (1 < yourtm
.tm_mon
);
1437 yourtm
.tm_mday
-= year_lengths
[isleap(i
)];
1438 if (increment_overflow(&yourtm
.tm_year
, 1))
1442 i
= mon_lengths
[isleap(yourtm
.tm_year
)][yourtm
.tm_mon
];
1443 if (yourtm
.tm_mday
<= i
)
1445 yourtm
.tm_mday
-= i
;
1446 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1448 if (increment_overflow(&yourtm
.tm_year
, 1))
1452 if (increment_overflow(&yourtm
.tm_year
, -TM_YEAR_BASE
))
1454 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1456 else if (yourtm
.tm_year
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1458 ** We can't set tm_sec to 0, because that might push the
1459 ** time below the minimum representable time.
1460 ** Set tm_sec to 59 instead.
1461 ** This assumes that the minimum representable time is
1462 ** not in the same minute that a leap second was deleted from,
1463 ** which is a safer assumption than using 58 would be.
1465 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1467 saved_seconds
= yourtm
.tm_sec
;
1468 yourtm
.tm_sec
= SECSPERMIN
- 1;
1470 saved_seconds
= yourtm
.tm_sec
;
1474 ** Divide the search space in half
1475 ** (this works whether time_t is signed or unsigned).
1477 bits
= TYPE_BIT(time_t) - 1;
1479 ** If we have more than this, we will overflow tm_year for tmcomp().
1480 ** We should really return an error if we cannot represent it.
1485 ** If time_t is signed, then 0 is just above the median,
1486 ** assuming two's complement arithmetic.
1487 ** If time_t is unsigned, then (1 << bits) is just above the median.
1489 t
= TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits
);
1491 (*funcp
)(&t
, offset
, &mytm
);
1492 dir
= tmcomp(&mytm
, &yourtm
);
1497 --t
; /* may be needed if new t is minimal */
1499 t
-= ((time_t) 1) << bits
;
1500 else t
+= ((time_t) 1) << bits
;
1503 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1506 ** Right time, wrong type.
1507 ** Hunt for right time, right type.
1508 ** It's okay to guess wrong since the guess
1512 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1514 sp
= (const struct state
*)
1515 (((void *) funcp
== (void *) localsub
) ?
1520 #endif /* defined ALL_STATE */
1521 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1522 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1524 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1525 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
1527 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
1528 sp
->ttis
[i
].tt_gmtoff
;
1529 (*funcp
)(&newt
, offset
, &mytm
);
1530 if (tmcomp(&mytm
, &yourtm
) != 0)
1532 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
1544 newt
= t
+ saved_seconds
;
1545 if ((newt
< t
) != (saved_seconds
< 0))
1548 (*funcp
)(&t
, offset
, tmp
);
1554 time1(tmp
, funcp
, offset
)
1555 struct tm
* const tmp
;
1556 void (* const funcp
)(const time_t *, long, struct tm
*);
1560 const struct state
* sp
;
1564 if (tmp
->tm_isdst
> 1)
1566 t
= time2(tmp
, funcp
, offset
, &okay
);
1569 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1573 if (tmp
->tm_isdst
< 0)
1574 tmp
->tm_isdst
= 0; /* reset to std and try again */
1575 #endif /* defined PCTS */
1577 if (okay
|| tmp
->tm_isdst
< 0)
1579 #endif /* !defined PCTS */
1581 ** We're supposed to assume that somebody took a time of one type
1582 ** and did some math on it that yielded a "struct tm" that's bad.
1583 ** We try to divine the type they started from and adjust to the
1587 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1589 sp
= (const struct state
*) (((void *) funcp
== (void *) localsub
) ?
1594 #endif /* defined ALL_STATE */
1595 for (samei
= sp
->typecnt
- 1; samei
>= 0; --samei
) {
1596 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
1598 for (otheri
= sp
->typecnt
- 1; otheri
>= 0; --otheri
) {
1599 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
1601 tmp
->tm_sec
+= sp
->ttis
[otheri
].tt_gmtoff
-
1602 sp
->ttis
[samei
].tt_gmtoff
;
1603 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1604 t
= time2(tmp
, funcp
, offset
, &okay
);
1607 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
1608 sp
->ttis
[samei
].tt_gmtoff
;
1609 tmp
->tm_isdst
= !tmp
->tm_isdst
;
1617 struct tm
* const tmp
;
1619 time_t mktime_return_value
;
1620 _MUTEX_LOCK(&lcl_mutex
);
1622 mktime_return_value
= time1(tmp
, localsub
, 0L);
1623 _MUTEX_UNLOCK(&lcl_mutex
);
1624 return(mktime_return_value
);
1631 struct tm
* const tmp
;
1633 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
1639 struct tm
* const tmp
;
1642 return time1(tmp
, gmtsub
, 0L);
1646 timeoff(tmp
, offset
)
1647 struct tm
* const tmp
;
1651 return time1(tmp
, gmtsub
, offset
);
1654 #endif /* defined STD_INSPIRED */
1659 ** The following is supplied for compatibility with
1660 ** previous versions of the CMUCS runtime library.
1665 struct tm
* const tmp
;
1667 const time_t t
= mktime(tmp
);
1674 #endif /* defined CMUCS */
1677 ** XXX--is the below the right way to conditionalize??
1683 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
1684 ** shall correspond to "Wed Dec 31 23:59:59 GMT 1986", which
1685 ** is not the case if we are accounting for leap seconds.
1686 ** So, we provide the following conversion routines for use
1687 ** when exchanging timestamps with POSIX conforming systems.
1702 if (*timep
>= lp
->ls_trans
)
1713 return t
- leapcorr(&t
);
1725 ** For a positive leap second hit, the result
1726 ** is not unique. For a negative leap second
1727 ** hit, the corresponding time doesn't exist,
1728 ** so we return an adjacent second.
1730 x
= t
+ leapcorr(&t
);
1731 y
= x
- leapcorr(&x
);
1735 y
= x
- leapcorr(&x
);
1742 y
= x
- leapcorr(&x
);
1750 #endif /* defined STD_INSPIRED */