1 /* $NetBSD: localtime.c,v 1.67 2012/03/20 16:39:08 matt 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.67 2012/03/20 16:39:08 matt 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"
28 #include "reentrant.h"
30 #if defined(__weak_alias)
31 __weak_alias(daylight
,_daylight
)
32 __weak_alias(tzname
,_tzname
)
35 #include "float.h" /* for FLT_MAX and DBL_MAX */
37 #ifndef TZ_ABBR_MAX_LEN
38 #define TZ_ABBR_MAX_LEN 16
39 #endif /* !defined TZ_ABBR_MAX_LEN */
41 #ifndef TZ_ABBR_CHAR_SET
42 #define TZ_ABBR_CHAR_SET \
43 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
44 #endif /* !defined TZ_ABBR_CHAR_SET */
46 #ifndef TZ_ABBR_ERR_CHAR
47 #define TZ_ABBR_ERR_CHAR '_'
48 #endif /* !defined TZ_ABBR_ERR_CHAR */
51 ** SunOS 4.1.1 headers lack O_BINARY.
55 #define OPEN_MODE (O_RDONLY | O_BINARY)
56 #endif /* defined O_BINARY */
58 #define OPEN_MODE O_RDONLY
59 #endif /* !defined O_BINARY */
63 ** Someone might make incorrect use of a time zone abbreviation:
64 ** 1. They might reference tzname[0] before calling tzset (explicitly
66 ** 2. They might reference tzname[1] before calling tzset (explicitly
68 ** 3. They might reference tzname[1] after setting to a time zone
69 ** in which Daylight Saving Time is never observed.
70 ** 4. They might reference tzname[0] after setting to a time zone
71 ** in which Standard Time is never observed.
72 ** 5. They might reference tm.TM_ZONE after calling offtime.
73 ** What's best to do in the above cases is open to debate;
74 ** for now, we just set things up so that in any of the five cases
75 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
76 ** string "tzname[0] used before set", and similarly for the other cases.
77 ** And another: initialize tzname[0] to "ERA", with an explanation in the
78 ** manual page of what this "time zone abbreviation" means (doing this so
79 ** that tzname[0] has the "normal" length of three characters).
82 #endif /* !defined WILDABBR */
84 static const char wildabbr
[] = WILDABBR
;
86 static char gmt
[] = "GMT";
89 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
90 ** We default to US rules as of 1999-08-17.
91 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
92 ** implementation dependent; for historical reasons, US rules are a
95 #ifndef TZDEFRULESTRING
96 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
97 #endif /* !defined TZDEFDST */
99 struct ttinfo
{ /* time type information */
100 long tt_gmtoff
; /* UTC offset in seconds */
101 int tt_isdst
; /* used to set tm_isdst */
102 int tt_abbrind
; /* abbreviation list index */
103 int tt_ttisstd
; /* TRUE if transition is std time */
104 int tt_ttisgmt
; /* TRUE if transition is UTC */
107 struct lsinfo
{ /* leap second information */
108 time_t ls_trans
; /* transition time */
109 long ls_corr
; /* correction to apply */
112 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
115 #define MY_TZNAME_MAX TZNAME_MAX
116 #endif /* defined TZNAME_MAX */
118 #define MY_TZNAME_MAX 255
119 #endif /* !defined TZNAME_MAX */
128 time_t ats
[TZ_MAX_TIMES
];
129 unsigned char types
[TZ_MAX_TIMES
];
130 struct ttinfo ttis
[TZ_MAX_TYPES
];
131 char chars
[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
132 (2 * (MY_TZNAME_MAX
+ 1)))];
133 struct lsinfo lsis
[TZ_MAX_LEAPS
];
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 long 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 long offset
, struct tm
*tmp
);
152 ** Prototypes for static functions.
155 static long 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
);
159 static const char * getqzname(const char * strp
, const int delim
);
160 static const char * getnum(const char * strp
, int * nump
, int min
,
162 static const char * getsecs(const char * strp
, long * secsp
);
163 static const char * getoffset(const char * strp
, long * 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 long offset
, struct tm
* tmp
);
168 static struct tm
* localsub(const timezone_t sp
, const time_t *timep
,
169 long offset
, struct tm
*tmp
);
170 static int increment_overflow(int * number
, int delta
);
171 static int leaps_thru_end_of(int y
);
172 static int long_increment_overflow(long * number
, int delta
);
173 static int long_normalize_overflow(long * tensptr
,
174 int * unitsptr
, int base
);
175 static int normalize_overflow(int * tensptr
, int * unitsptr
,
177 static void settzname(void);
178 static time_t time1(const timezone_t sp
, struct tm
* const tmp
,
179 subfun_t funcp
, long offset
);
180 static time_t time2(const timezone_t sp
, struct tm
* const tmp
,
182 const long offset
, int *const okayp
);
183 static time_t time2sub(const timezone_t sp
, struct tm
* consttmp
,
184 subfun_t funcp
, const long offset
,
185 int *const okayp
, const int do_norm_secs
);
186 static struct tm
* timesub(const timezone_t sp
, const time_t * timep
,
187 long 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
, long offset
);
192 static int typesequiv(const timezone_t sp
, int a
, int b
);
193 static int tzload(timezone_t sp
, const char * name
,
195 static int tzparse(timezone_t sp
, const char * name
,
197 static void tzset_unlocked(void);
198 static void tzsetwall_unlocked(void);
199 static long leapcorr(const timezone_t sp
, time_t * timep
);
201 static timezone_t lclptr
;
202 static timezone_t gmtptr
;
204 #ifndef TZ_STRLEN_MAX
205 #define TZ_STRLEN_MAX 255
206 #endif /* !defined TZ_STRLEN_MAX */
208 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
209 static int lcl_is_set
;
210 static int gmt_is_set
;
212 #if !defined(__LIBC12_SOURCE__)
214 __aconst
char * tzname
[2] = {
215 (__aconst
char *)__UNCONST(wildabbr
),
216 (__aconst
char *)__UNCONST(wildabbr
)
221 extern __aconst
char * tzname
[2];
226 static rwlock_t lcl_lock
= RWLOCK_INITIALIZER
;
230 ** Section 4.12.3 of X3.159-1989 requires that
231 ** Except for the strftime function, these functions [asctime,
232 ** ctime, gmtime, localtime] return values in one of two static
233 ** objects: a broken-down time structure and an array of char.
234 ** Thanks to Paul Eggert for noting this.
240 #if !defined(__LIBC12_SOURCE__)
245 extern long timezone
__RENAME(__timezone13
);
247 #endif /* defined USG_COMPAT */
251 #endif /* defined ALTZONE */
254 detzcode(const char *const codep
)
259 result
= (codep
[0] & 0x80) ? ~0L : 0;
260 for (i
= 0; i
< 4; ++i
)
261 result
= (result
<< 8) | (codep
[i
] & 0xff);
266 detzcode64(const char *const codep
)
271 result
= (codep
[0] & 0x80) ? -1 : 0;
272 for (i
= 0; i
< 8; ++i
)
273 result
= result
* 256 + (codep
[i
] & 0xff);
278 tzgetname(const timezone_t sp
, int isdst
)
281 for (i
= 0; i
< sp
->timecnt
; ++i
) {
282 const struct ttinfo
*const ttisp
= &sp
->ttis
[sp
->types
[i
]];
284 if (ttisp
->tt_isdst
== isdst
)
285 return &sp
->chars
[ttisp
->tt_abbrind
];
291 settzname_z(timezone_t sp
)
296 ** Scrub the abbreviations.
297 ** First, replace bogus characters.
299 for (i
= 0; i
< sp
->charcnt
; ++i
)
300 if (strchr(TZ_ABBR_CHAR_SET
, sp
->chars
[i
]) == NULL
)
301 sp
->chars
[i
] = TZ_ABBR_ERR_CHAR
;
303 ** Second, truncate long abbreviations.
305 for (i
= 0; i
< sp
->typecnt
; ++i
) {
306 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
307 char * cp
= &sp
->chars
[ttisp
->tt_abbrind
];
309 if (strlen(cp
) > TZ_ABBR_MAX_LEN
&&
310 strcmp(cp
, GRANDPARENTED
) != 0)
311 *(cp
+ TZ_ABBR_MAX_LEN
) = '\0';
318 timezone_t
const sp
= lclptr
;
321 tzname
[0] = (__aconst
char *)__UNCONST(wildabbr
);
322 tzname
[1] = (__aconst
char *)__UNCONST(wildabbr
);
326 #endif /* defined USG_COMPAT */
329 #endif /* defined ALTZONE */
331 tzname
[0] = tzname
[1] = (__aconst
char *)__UNCONST(gmt
);
335 ** And to get the latest zone names into tzname. . .
337 for (i
= 0; i
< sp
->typecnt
; ++i
) {
338 const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
340 tzname
[ttisp
->tt_isdst
] =
341 &sp
->chars
[ttisp
->tt_abbrind
];
345 if (!ttisp
->tt_isdst
)
346 timezone
= -(ttisp
->tt_gmtoff
);
347 #endif /* defined USG_COMPAT */
349 if (i
== 0 || ttisp
->tt_isdst
)
350 altzone
= -(ttisp
->tt_gmtoff
);
351 #endif /* defined ALTZONE */
357 differ_by_repeat(const time_t t1
, const time_t t0
)
360 if (TYPE_INTEGRAL(time_t) &&
361 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
363 return (int_fast64_t)t1
- (int_fast64_t)t0
== SECSPERREPEAT
;
367 tzload(timezone_t sp
, const char *name
, const int doextend
)
375 struct tzhead tzhead
;
376 char buf
[2 * sizeof(struct tzhead
) +
382 up
= calloc(1, sizeof *up
);
386 sp
->goback
= sp
->goahead
= FALSE
;
387 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
392 ** Section 4.9.1 of the C standard says that
393 ** "FILENAME_MAX expands to an integral constant expression
394 ** that is the size needed for an array of char large enough
395 ** to hold the longest file name string that the implementation
396 ** guarantees can be opened."
398 char fullname
[FILENAME_MAX
+ 1];
402 doaccess
= name
[0] == '/';
404 if ((p
= TZDIR
) == NULL
)
406 if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
408 (void) strcpy(fullname
, p
); /* XXX strcpy is safe */
409 (void) strcat(fullname
, "/"); /* XXX strcat is safe */
410 (void) strcat(fullname
, name
); /* XXX strcat is safe */
412 ** Set doaccess if '.' (as in "../") shows up in name.
414 if (strchr(name
, '.') != NULL
)
418 if (doaccess
&& access(name
, R_OK
) != 0)
421 * XXX potential security problem here if user of a set-id
422 * program has set TZ (which is passed in as name) here,
423 * and uses a race condition trick to defeat the access(2)
426 if ((fid
= open(name
, OPEN_MODE
)) == -1)
429 nread
= read(fid
, up
->buf
, sizeof up
->buf
);
430 if (close(fid
) < 0 || nread
<= 0)
432 for (stored
= 4; stored
<= 8; stored
*= 2) {
436 ttisstdcnt
= (int) detzcode(up
->tzhead
.tzh_ttisstdcnt
);
437 ttisgmtcnt
= (int) detzcode(up
->tzhead
.tzh_ttisgmtcnt
);
438 sp
->leapcnt
= (int) detzcode(up
->tzhead
.tzh_leapcnt
);
439 sp
->timecnt
= (int) detzcode(up
->tzhead
.tzh_timecnt
);
440 sp
->typecnt
= (int) detzcode(up
->tzhead
.tzh_typecnt
);
441 sp
->charcnt
= (int) detzcode(up
->tzhead
.tzh_charcnt
);
442 p
= up
->tzhead
.tzh_charcnt
+ sizeof up
->tzhead
.tzh_charcnt
;
443 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
444 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
445 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
446 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
447 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
448 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
450 if (nread
- (p
- up
->buf
) <
451 sp
->timecnt
* stored
+ /* ats */
452 sp
->timecnt
+ /* types */
453 sp
->typecnt
* 6 + /* ttinfos */
454 sp
->charcnt
+ /* chars */
455 sp
->leapcnt
* (stored
+ 4) + /* lsinfos */
456 ttisstdcnt
+ /* ttisstds */
457 ttisgmtcnt
) /* ttisgmts */
459 for (i
= 0; i
< sp
->timecnt
; ++i
) {
460 sp
->ats
[i
] = (time_t)((stored
== 4) ?
461 detzcode(p
) : detzcode64(p
));
464 for (i
= 0; i
< sp
->timecnt
; ++i
) {
465 sp
->types
[i
] = (unsigned char) *p
++;
466 if (sp
->types
[i
] >= sp
->typecnt
)
469 for (i
= 0; i
< sp
->typecnt
; ++i
) {
470 struct ttinfo
* ttisp
;
472 ttisp
= &sp
->ttis
[i
];
473 ttisp
->tt_gmtoff
= detzcode(p
);
475 ttisp
->tt_isdst
= (unsigned char) *p
++;
476 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
478 ttisp
->tt_abbrind
= (unsigned char) *p
++;
479 if (ttisp
->tt_abbrind
< 0 ||
480 ttisp
->tt_abbrind
> sp
->charcnt
)
483 for (i
= 0; i
< sp
->charcnt
; ++i
)
485 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
486 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
487 struct lsinfo
* lsisp
;
489 lsisp
= &sp
->lsis
[i
];
490 lsisp
->ls_trans
= (time_t)((stored
== 4) ?
491 detzcode(p
) : detzcode64(p
));
493 lsisp
->ls_corr
= detzcode(p
);
496 for (i
= 0; i
< sp
->typecnt
; ++i
) {
497 struct ttinfo
* ttisp
;
499 ttisp
= &sp
->ttis
[i
];
501 ttisp
->tt_ttisstd
= FALSE
;
503 ttisp
->tt_ttisstd
= *p
++;
504 if (ttisp
->tt_ttisstd
!= TRUE
&&
505 ttisp
->tt_ttisstd
!= FALSE
)
509 for (i
= 0; i
< sp
->typecnt
; ++i
) {
510 struct ttinfo
* ttisp
;
512 ttisp
= &sp
->ttis
[i
];
514 ttisp
->tt_ttisgmt
= FALSE
;
516 ttisp
->tt_ttisgmt
= *p
++;
517 if (ttisp
->tt_ttisgmt
!= TRUE
&&
518 ttisp
->tt_ttisgmt
!= FALSE
)
523 ** Out-of-sort ats should mean we're running on a
524 ** signed time_t system but using a data file with
525 ** unsigned values (or vice versa).
527 for (i
= 0; i
< sp
->timecnt
- 2; ++i
)
528 if (sp
->ats
[i
] > sp
->ats
[i
+ 1]) {
531 if (TYPE_SIGNED(time_t)) {
533 ** Ignore the end (easy).
538 ** Ignore the beginning (harder).
542 for (j
= 0; j
+ i
< sp
->timecnt
; ++j
) {
543 sp
->ats
[j
] = sp
->ats
[j
+ i
];
544 sp
->types
[j
] = sp
->types
[j
+ i
];
551 ** If this is an old file, we're done.
553 if (up
->tzhead
.tzh_version
[0] == '\0')
555 nread
-= p
- up
->buf
;
556 for (i
= 0; i
< nread
; ++i
)
559 ** If this is a narrow integer time_t system, we're done.
561 if (stored
>= (int) sizeof(time_t)
563 && TYPE_INTEGRAL(time_t))
566 if (doextend
&& nread
> 2 &&
567 up
->buf
[0] == '\n' && up
->buf
[nread
- 1] == '\n' &&
568 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
572 up
->buf
[nread
- 1] = '\0';
573 result
= tzparse(&ts
, &up
->buf
[1], FALSE
);
574 if (result
== 0 && ts
.typecnt
== 2 &&
575 sp
->charcnt
+ ts
.charcnt
<= TZ_MAX_CHARS
) {
576 for (i
= 0; i
< 2; ++i
)
577 ts
.ttis
[i
].tt_abbrind
+=
579 for (i
= 0; i
< ts
.charcnt
; ++i
)
580 sp
->chars
[sp
->charcnt
++] =
583 while (i
< ts
.timecnt
&&
585 sp
->ats
[sp
->timecnt
- 1])
587 while (i
< ts
.timecnt
&&
588 sp
->timecnt
< TZ_MAX_TIMES
) {
589 sp
->ats
[sp
->timecnt
] =
591 sp
->types
[sp
->timecnt
] =
597 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
598 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
601 if (sp
->timecnt
> 1) {
602 for (i
= 1; i
< sp
->timecnt
; ++i
)
603 if (typesequiv(sp
, sp
->types
[i
], sp
->types
[0]) &&
604 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0])) {
608 for (i
= sp
->timecnt
- 2; i
>= 0; --i
)
609 if (typesequiv(sp
, sp
->types
[sp
->timecnt
- 1],
611 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
625 typesequiv(const timezone_t sp
, const int a
, const int b
)
630 a
< 0 || a
>= sp
->typecnt
||
631 b
< 0 || b
>= sp
->typecnt
)
634 const struct ttinfo
* ap
= &sp
->ttis
[a
];
635 const struct ttinfo
* bp
= &sp
->ttis
[b
];
636 result
= ap
->tt_gmtoff
== bp
->tt_gmtoff
&&
637 ap
->tt_isdst
== bp
->tt_isdst
&&
638 ap
->tt_ttisstd
== bp
->tt_ttisstd
&&
639 ap
->tt_ttisgmt
== bp
->tt_ttisgmt
&&
640 strcmp(&sp
->chars
[ap
->tt_abbrind
],
641 &sp
->chars
[bp
->tt_abbrind
]) == 0;
646 static const int mon_lengths
[2][MONSPERYEAR
] = {
647 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
648 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
651 static const int year_lengths
[2] = {
652 DAYSPERNYEAR
, DAYSPERLYEAR
656 ** Given a pointer into a time zone string, scan until a character that is not
657 ** a valid character in a zone name is found. Return a pointer to that
662 getzname(const char *strp
)
666 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
673 ** Given a pointer into an extended time zone string, scan until the ending
674 ** delimiter of the zone name is located. Return a pointer to the delimiter.
676 ** As with getzname above, the legal character set is actually quite
677 ** restricted, with other characters producing undefined results.
678 ** We don't do any checking here; checking is done later in common-case code.
682 getqzname(const char *strp
, const int delim
)
686 while ((c
= *strp
) != '\0' && c
!= delim
)
692 ** Given a pointer into a time zone string, extract a number from that string.
693 ** Check that the number is within a specified range; if it is not, return
695 ** Otherwise, return a pointer to the first character not part of the number.
699 getnum(const char *strp
, int * const nump
, const int min
, const int max
)
704 if (strp
== NULL
|| !is_digit(c
= *strp
)) {
710 num
= num
* 10 + (c
- '0');
713 return NULL
; /* illegal value */
716 } while (is_digit(c
));
719 return NULL
; /* illegal value */
726 ** Given a pointer into a time zone string, extract a number of seconds,
727 ** in hh[:mm[:ss]] form, from the string.
728 ** If any error occurs, return NULL.
729 ** Otherwise, return a pointer to the first character not part of the number
734 getsecs(const char *strp
, long *const secsp
)
739 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
740 ** "M10.4.6/26", which does not conform to Posix,
741 ** but which specifies the equivalent of
742 ** ``02:00 on the first Sunday on or after 23 Oct''.
744 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
747 *secsp
= num
* (long) SECSPERHOUR
;
750 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
753 *secsp
+= num
* SECSPERMIN
;
756 /* `SECSPERMIN' allows for leap seconds. */
757 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
767 ** Given a pointer into a time zone string, extract an offset, in
768 ** [+-]hh[:mm[:ss]] form, from the string.
769 ** If any error occurs, return NULL.
770 ** Otherwise, return a pointer to the first character not part of the time.
774 getoffset(const char *strp
, long *const offsetp
)
781 } else if (*strp
== '+')
783 strp
= getsecs(strp
, offsetp
);
785 return NULL
; /* illegal time */
787 *offsetp
= -*offsetp
;
792 ** Given a pointer into a time zone string, extract a rule in the form
793 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
794 ** If a valid rule is not found, return NULL.
795 ** Otherwise, return a pointer to the first character not part of the rule.
799 getrule(const char *strp
, struct rule
*const rulep
)
805 rulep
->r_type
= JULIAN_DAY
;
807 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
808 } else if (*strp
== 'M') {
812 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
814 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
819 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
824 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
825 } else if (is_digit(*strp
)) {
829 rulep
->r_type
= DAY_OF_YEAR
;
830 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
831 } else return NULL
; /* invalid format */
839 strp
= getsecs(strp
, &rulep
->r_time
);
840 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
845 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
846 ** year, a rule, and the offset from UTC at the time that rule takes effect,
847 ** calculate the Epoch-relative time that rule takes effect.
851 transtime(const time_t janfirst
, const int year
, const struct rule
*const rulep
,
857 int d
, m1
, yy0
, yy1
, yy2
, dow
;
860 leapyear
= isleap(year
);
861 switch (rulep
->r_type
) {
865 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
867 ** In non-leap years, or if the day number is 59 or less, just
868 ** add SECSPERDAY times the day number-1 to the time of
869 ** January 1, midnight, to get the day.
871 value
= (time_t)(janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
);
872 if (leapyear
&& rulep
->r_day
>= 60)
879 ** Just add SECSPERDAY times the day number to the time of
880 ** January 1, midnight, to get the day.
882 value
= (time_t)(janfirst
+ rulep
->r_day
* SECSPERDAY
);
885 case MONTH_NTH_DAY_OF_WEEK
:
887 ** Mm.n.d - nth "dth day" of month m.
890 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
891 value
+= (time_t)(mon_lengths
[leapyear
][i
] * SECSPERDAY
);
894 ** Use Zeller's Congruence to get day-of-week of first day of
897 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
898 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
901 dow
= ((26 * m1
- 2) / 10 +
902 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
907 ** "dow" is the day-of-week of the first day of the month. Get
908 ** the day-of-month (zero-origin) of the first "dow" day of the
911 d
= rulep
->r_day
- dow
;
914 for (i
= 1; i
< rulep
->r_week
; ++i
) {
915 if (d
+ DAYSPERWEEK
>=
916 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
922 ** "d" is the day-of-month (zero-origin) of the day we want.
924 value
+= (time_t)(d
* SECSPERDAY
);
929 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
930 ** question. To get the Epoch-relative time of the specified local
931 ** time on that day, add the transition time and the current offset
934 return (time_t)(value
+ rulep
->r_time
+ offset
);
938 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
943 tzparse(timezone_t sp
, const char *name
, const int lastditch
)
945 const char * stdname
;
946 const char * dstname
;
952 unsigned char * typep
;
959 stdlen
= strlen(name
); /* length of standard zone name */
961 if (stdlen
>= sizeof sp
->chars
)
962 stdlen
= (sizeof sp
->chars
) - 1;
968 name
= getqzname(name
, '>');
971 stdlen
= name
- stdname
;
974 name
= getzname(name
);
975 stdlen
= name
- stdname
;
979 name
= getoffset(name
, &stdoffset
);
983 load_result
= tzload(sp
, TZDEFRULES
, FALSE
);
984 if (load_result
!= 0)
985 sp
->leapcnt
= 0; /* so, we're off a little */
989 name
= getqzname(name
, '>');
992 dstlen
= name
- dstname
;
996 name
= getzname(name
);
997 dstlen
= name
- dstname
; /* length of DST zone name */
999 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1000 name
= getoffset(name
, &dstoffset
);
1003 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1004 if (*name
== '\0' && load_result
!= 0)
1005 name
= TZDEFRULESTRING
;
1006 if (*name
== ',' || *name
== ';') {
1015 if ((name
= getrule(name
, &start
)) == NULL
)
1019 if ((name
= getrule(name
, &end
)) == NULL
)
1023 sp
->typecnt
= 2; /* standard time and DST */
1025 ** Two transitions per year, from EPOCH_YEAR forward.
1027 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1028 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
1029 sp
->ttis
[0].tt_isdst
= 1;
1030 sp
->ttis
[0].tt_abbrind
= (int)(stdlen
+ 1);
1031 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
1032 sp
->ttis
[1].tt_isdst
= 0;
1033 sp
->ttis
[1].tt_abbrind
= 0;
1038 for (year
= EPOCH_YEAR
;
1039 sp
->timecnt
+ 2 <= TZ_MAX_TIMES
;
1043 starttime
= transtime(janfirst
, year
, &start
,
1045 endtime
= transtime(janfirst
, year
, &end
,
1047 if (starttime
> endtime
) {
1049 *typep
++ = 1; /* DST ends */
1051 *typep
++ = 0; /* DST begins */
1054 *typep
++ = 0; /* DST begins */
1056 *typep
++ = 1; /* DST ends */
1059 newfirst
= janfirst
;
1060 newfirst
+= (time_t)
1061 (year_lengths
[isleap(year
)] * SECSPERDAY
);
1062 if (newfirst
<= janfirst
)
1064 janfirst
= newfirst
;
1067 long theirstdoffset
;
1068 long theirdstoffset
;
1077 ** Initial values of theirstdoffset
1080 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1082 if (!sp
->ttis
[j
].tt_isdst
) {
1084 -sp
->ttis
[j
].tt_gmtoff
;
1089 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1091 if (sp
->ttis
[j
].tt_isdst
) {
1093 -sp
->ttis
[j
].tt_gmtoff
;
1098 ** Initially we're assumed to be in standard time.
1101 theiroffset
= theirstdoffset
;
1103 ** Now juggle transition times and types
1104 ** tracking offsets as you do.
1106 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1108 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1109 if (sp
->ttis
[j
].tt_ttisgmt
) {
1110 /* No adjustment to transition time */
1113 ** If summer time is in effect, and the
1114 ** transition time was not specified as
1115 ** standard time, add the summer time
1116 ** offset to the transition time;
1117 ** otherwise, add the standard time
1118 ** offset to the transition time.
1121 ** Transitions from DST to DDST
1122 ** will effectively disappear since
1123 ** POSIX provides for only one DST
1126 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1127 sp
->ats
[i
] += (time_t)
1128 (dstoffset
- theirdstoffset
);
1130 sp
->ats
[i
] += (time_t)
1131 (stdoffset
- theirstdoffset
);
1134 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1135 if (!sp
->ttis
[j
].tt_isdst
)
1136 theirstdoffset
= theiroffset
;
1137 else theirdstoffset
= theiroffset
;
1140 ** Finally, fill in ttis.
1142 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1143 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1144 sp
->ttis
[0].tt_isdst
= FALSE
;
1145 sp
->ttis
[0].tt_abbrind
= 0;
1146 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1147 sp
->ttis
[1].tt_isdst
= TRUE
;
1148 sp
->ttis
[1].tt_abbrind
= (int)(stdlen
+ 1);
1153 sp
->typecnt
= 1; /* only standard time */
1155 memset(sp
->ttis
, 0, sizeof(sp
->ttis
));
1156 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1157 sp
->ttis
[0].tt_isdst
= 0;
1158 sp
->ttis
[0].tt_abbrind
= 0;
1160 sp
->charcnt
= (int)(stdlen
+ 1);
1162 sp
->charcnt
+= (int)(dstlen
+ 1);
1163 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1166 (void) strncpy(cp
, stdname
, stdlen
);
1170 (void) strncpy(cp
, dstname
, dstlen
);
1171 *(cp
+ dstlen
) = '\0';
1177 gmtload(timezone_t sp
)
1179 if (tzload(sp
, gmt
, TRUE
) != 0)
1180 (void) tzparse(sp
, gmt
, TRUE
);
1184 tzalloc(const char *name
)
1186 timezone_t sp
= calloc(1, sizeof *sp
);
1189 if (tzload(sp
, name
, TRUE
) != 0) {
1198 tzfree(const timezone_t sp
)
1204 tzsetwall_unlocked(void)
1210 if (lclptr
== NULL
) {
1211 int saveerrno
= errno
;
1212 lclptr
= calloc(1, sizeof *lclptr
);
1214 if (lclptr
== NULL
) {
1215 settzname(); /* all we can do */
1219 if (tzload(lclptr
, NULL
, TRUE
) != 0)
1224 #ifndef STD_INSPIRED
1226 ** A non-static declaration of tzsetwall in a system header file
1227 ** may cause a warning about this upcoming static declaration...
1230 #endif /* !defined STD_INSPIRED */
1234 rwlock_wrlock(&lcl_lock
);
1235 tzsetwall_unlocked();
1236 rwlock_unlock(&lcl_lock
);
1239 #ifndef STD_INSPIRED
1241 ** A non-static declaration of tzsetwall in a system header file
1242 ** may cause a warning about this upcoming static declaration...
1245 #endif /* !defined STD_INSPIRED */
1247 tzset_unlocked(void)
1253 name
= getenv("TZ");
1256 tzsetwall_unlocked();
1260 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1262 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1264 (void)strlcpy(lcl_TZname
, name
, sizeof(lcl_TZname
));
1266 if (lclptr
== NULL
) {
1268 lclptr
= calloc(1, sizeof *lclptr
);
1270 if (lclptr
== NULL
) {
1271 settzname(); /* all we can do */
1275 if (*name
== '\0') {
1277 ** User wants it fast rather than right.
1279 lclptr
->leapcnt
= 0; /* so, we're off a little */
1280 lclptr
->timecnt
= 0;
1281 lclptr
->typecnt
= 0;
1282 lclptr
->ttis
[0].tt_isdst
= 0;
1283 lclptr
->ttis
[0].tt_gmtoff
= 0;
1284 lclptr
->ttis
[0].tt_abbrind
= 0;
1285 (void) strlcpy(lclptr
->chars
, gmt
, sizeof(lclptr
->chars
));
1286 } else if (tzload(lclptr
, name
, TRUE
) != 0)
1287 if (name
[0] == ':' || tzparse(lclptr
, name
, FALSE
) != 0)
1288 (void) gmtload(lclptr
);
1295 rwlock_wrlock(&lcl_lock
);
1297 rwlock_unlock(&lcl_lock
);
1301 ** The easy way to behave "as if no library function calls" localtime
1302 ** is to not call it--so we drop its guts into "localsub", which can be
1303 ** freely called. (And no, the PANS doesn't require the above behavior--
1304 ** but it *is* desirable.)
1306 ** The unused offset argument is for the benefit of mktime variants.
1311 localsub(const timezone_t sp
, const time_t * const timep
, const long offset
,
1312 struct tm
*const tmp
)
1314 const struct ttinfo
* ttisp
;
1317 const time_t t
= *timep
;
1319 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1320 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1324 int_fast64_t icycles
;
1327 seconds
= sp
->ats
[0] - t
;
1328 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1331 (seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
);
1334 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
1336 seconds
= (time_t) icycles
;
1337 seconds
*= YEARSPERREPEAT
;
1338 seconds
*= AVGSECSPERYEAR
;
1341 else newt
-= seconds
;
1342 if (newt
< sp
->ats
[0] ||
1343 newt
> sp
->ats
[sp
->timecnt
- 1])
1344 return NULL
; /* "cannot happen" */
1345 result
= localsub(sp
, &newt
, offset
, tmp
);
1346 if (result
== tmp
) {
1349 newy
= tmp
->tm_year
;
1351 newy
-= (time_t)icycles
* YEARSPERREPEAT
;
1352 else newy
+= (time_t)icycles
* YEARSPERREPEAT
;
1353 tmp
->tm_year
= (int)newy
;
1354 if (tmp
->tm_year
!= newy
)
1359 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1361 while (sp
->ttis
[i
].tt_isdst
)
1362 if (++i
>= sp
->typecnt
) {
1368 int hi
= sp
->timecnt
;
1371 int mid
= (lo
+ hi
) / 2;
1373 if (t
< sp
->ats
[mid
])
1377 i
= (int) sp
->types
[lo
- 1];
1379 ttisp
= &sp
->ttis
[i
];
1381 ** To get (wrong) behavior that's compatible with System V Release 2.0
1382 ** you'd replace the statement below with
1383 ** t += ttisp->tt_gmtoff;
1384 ** timesub(&t, 0L, sp, tmp);
1386 result
= timesub(sp
, &t
, ttisp
->tt_gmtoff
, tmp
);
1387 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1389 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1391 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1392 #endif /* defined TM_ZONE */
1397 ** Re-entrant version of localtime.
1401 localtime_r(const time_t * __restrict timep
, struct tm
*tmp
)
1403 rwlock_rdlock(&lcl_lock
);
1405 tmp
= localtime_rz(lclptr
, timep
, tmp
);
1406 rwlock_unlock(&lcl_lock
);
1411 localtime(const time_t *const timep
)
1413 return localtime_r(timep
, &tm
);
1417 localtime_rz(const timezone_t sp
, const time_t * __restrict timep
, struct tm
*tmp
)
1420 tmp
= gmtsub(NULL
, timep
, 0L, tmp
);
1422 tmp
= localsub(sp
, timep
, 0L, tmp
);
1429 ** gmtsub is to gmtime as localsub is to localtime.
1433 gmtsub(const timezone_t sp
, const time_t * const timep
, const long offset
,
1434 struct tm
*const tmp
)
1438 static mutex_t gmt_mutex
= MUTEX_INITIALIZER
;
1441 mutex_lock(&gmt_mutex
);
1446 gmtptr
= calloc(1, sizeof *gmtptr
);
1451 mutex_unlock(&gmt_mutex
);
1452 result
= timesub(gmtptr
, timep
, offset
, tmp
);
1455 ** Could get fancy here and deliver something such as
1456 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1457 ** but this is no time for a treasure hunt.
1460 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(wildabbr
);
1463 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(gmt
);
1464 else tmp
->TM_ZONE
= gmtptr
->chars
;
1466 #endif /* defined TM_ZONE */
1471 gmtime(const time_t *const timep
)
1473 struct tm
*tmp
= gmtsub(NULL
, timep
, 0L, &tm
);
1482 ** Re-entrant version of gmtime.
1486 gmtime_r(const time_t * const timep
, struct tm
*tmp
)
1488 tmp
= gmtsub(NULL
, timep
, 0L, tmp
);
1499 offtime(const time_t *const timep
, long offset
)
1501 struct tm
*tmp
= gmtsub(NULL
, timep
, offset
, &tm
);
1510 offtime_r(const time_t *timep
, long offset
, struct tm
*tmp
)
1512 tmp
= gmtsub(NULL
, timep
, offset
, tmp
);
1520 #endif /* defined STD_INSPIRED */
1523 ** Return the number of leap years through the end of the given year
1524 ** where, to make the math easy, the answer for year zero is defined as zero.
1528 leaps_thru_end_of(const int y
)
1530 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1531 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1535 timesub(const timezone_t sp
, const time_t *const timep
, const long offset
,
1536 struct tm
*const tmp
)
1538 const struct lsinfo
* lp
;
1540 int idays
; /* unsigned would be so 2003 */
1550 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1553 if (*timep
>= lp
->ls_trans
) {
1554 if (*timep
== lp
->ls_trans
) {
1555 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
1556 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
1559 sp
->lsis
[i
].ls_trans
==
1560 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
1561 sp
->lsis
[i
].ls_corr
==
1562 sp
->lsis
[i
- 1].ls_corr
+ 1) {
1572 tdays
= (time_t)(*timep
/ SECSPERDAY
);
1573 rem
= (long) (*timep
- tdays
* SECSPERDAY
);
1574 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1580 tdelta
= tdays
/ DAYSPERLYEAR
;
1581 idelta
= (int) tdelta
;
1582 if (tdelta
- idelta
>= 1 || idelta
- tdelta
>= 1)
1585 idelta
= (tdays
< 0) ? -1 : 1;
1587 if (increment_overflow(&newy
, idelta
))
1589 leapdays
= leaps_thru_end_of(newy
- 1) -
1590 leaps_thru_end_of(y
- 1);
1591 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
1598 seconds
= tdays
* SECSPERDAY
+ 0.5;
1599 tdays
= (time_t)(seconds
/ SECSPERDAY
);
1600 rem
+= (long) (seconds
- tdays
* SECSPERDAY
);
1603 ** Given the range, we can now fearlessly cast...
1605 idays
= (int) tdays
;
1606 rem
+= offset
- corr
;
1611 while (rem
>= SECSPERDAY
) {
1616 if (increment_overflow(&y
, -1))
1618 idays
+= year_lengths
[isleap(y
)];
1620 while (idays
>= year_lengths
[isleap(y
)]) {
1621 idays
-= year_lengths
[isleap(y
)];
1622 if (increment_overflow(&y
, 1))
1626 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
1628 tmp
->tm_yday
= idays
;
1630 ** The "extra" mods below avoid overflow problems.
1632 tmp
->tm_wday
= EPOCH_WDAY
+
1633 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
1634 (DAYSPERNYEAR
% DAYSPERWEEK
) +
1635 leaps_thru_end_of(y
- 1) -
1636 leaps_thru_end_of(EPOCH_YEAR
- 1) +
1638 tmp
->tm_wday
%= DAYSPERWEEK
;
1639 if (tmp
->tm_wday
< 0)
1640 tmp
->tm_wday
+= DAYSPERWEEK
;
1641 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1643 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1645 ** A positive leap second requires a special
1646 ** representation. This uses "... ??:59:60" et seq.
1648 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
1649 ip
= mon_lengths
[isleap(y
)];
1650 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
1651 idays
-= ip
[tmp
->tm_mon
];
1652 tmp
->tm_mday
= (int) (idays
+ 1);
1655 tmp
->TM_GMTOFF
= offset
;
1656 #endif /* defined TM_GMTOFF */
1661 ctime(const time_t *const timep
)
1664 ** Section 4.12.3.2 of X3.159-1989 requires that
1665 ** The ctime function converts the calendar time pointed to by timer
1666 ** to local time in the form of a string. It is equivalent to
1667 ** asctime(localtime(timer))
1669 struct tm
*rtm
= localtime(timep
);
1672 return asctime(rtm
);
1676 ctime_r(const time_t *const timep
, char *buf
)
1678 struct tm mytm
, *rtm
;
1680 rtm
= localtime_r(timep
, &mytm
);
1683 return asctime_r(rtm
, buf
);
1687 ctime_rz(const timezone_t sp
, const time_t * timep
, char *buf
)
1689 struct tm mytm
, *rtm
;
1691 rtm
= localtime_rz(sp
, timep
, &mytm
);
1694 return asctime_r(rtm
, buf
);
1698 ** Adapted from code provided by Robert Elz, who writes:
1699 ** The "best" way to do mktime I think is based on an idea of Bob
1700 ** Kridle's (so its said...) from a long time ago.
1701 ** It does a binary search of the time_t space. Since time_t's are
1702 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1703 ** would still be very reasonable).
1707 #define WRONG ((time_t)-1)
1708 #endif /* !defined WRONG */
1711 ** Simplified normalize logic courtesy Paul Eggert.
1715 increment_overflow(int *ip
, int j
)
1720 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1721 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1722 ** If i < 0 there can only be overflow if i + j < INT_MIN
1723 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1725 if ((i
>= 0) ? (j
> INT_MAX
- i
) : (j
< INT_MIN
- i
))
1732 long_increment_overflow(long *lp
, int m
)
1736 if ((l
>= 0) ? (m
> LONG_MAX
- l
) : (m
< LONG_MIN
- l
))
1743 normalize_overflow(int *const tensptr
, int *const unitsptr
, const int base
)
1747 tensdelta
= (*unitsptr
>= 0) ?
1748 (*unitsptr
/ base
) :
1749 (-1 - (-1 - *unitsptr
) / base
);
1750 *unitsptr
-= tensdelta
* base
;
1751 return increment_overflow(tensptr
, tensdelta
);
1755 long_normalize_overflow(long *const tensptr
, int *const unitsptr
,
1760 tensdelta
= (*unitsptr
>= 0) ?
1761 (*unitsptr
/ base
) :
1762 (-1 - (-1 - *unitsptr
) / base
);
1763 *unitsptr
-= tensdelta
* base
;
1764 return long_increment_overflow(tensptr
, tensdelta
);
1768 tmcomp(const struct tm
*const atmp
, const struct tm
*const btmp
)
1772 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
1773 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1774 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1775 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1776 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1777 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1782 time2sub(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
1783 const long offset
, int *const okayp
, const int do_norm_secs
)
1791 #ifdef NO_ERROR_IN_DST_GAP
1797 struct tm yourtm
, mytm
;
1801 #ifdef NO_ERROR_IN_DST_GAP
1805 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1809 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1811 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1814 if (long_normalize_overflow(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1817 ** Turn y into an actual year number for now.
1818 ** It is converted back to an offset from TM_YEAR_BASE later.
1820 if (long_increment_overflow(&y
, TM_YEAR_BASE
))
1822 while (yourtm
.tm_mday
<= 0) {
1823 if (long_increment_overflow(&y
, -1))
1825 li
= y
+ (1 < yourtm
.tm_mon
);
1826 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1828 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1829 li
= y
+ (1 < yourtm
.tm_mon
);
1830 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1831 if (long_increment_overflow(&y
, 1))
1835 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1836 if (yourtm
.tm_mday
<= i
)
1838 yourtm
.tm_mday
-= i
;
1839 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1841 if (long_increment_overflow(&y
, 1))
1845 if (long_increment_overflow(&y
, -TM_YEAR_BASE
))
1847 yourtm
.tm_year
= (int)y
;
1848 if (yourtm
.tm_year
!= y
)
1850 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1852 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1854 ** We can't set tm_sec to 0, because that might push the
1855 ** time below the minimum representable time.
1856 ** Set tm_sec to 59 instead.
1857 ** This assumes that the minimum representable time is
1858 ** not in the same minute that a leap second was deleted from,
1859 ** which is a safer assumption than using 58 would be.
1861 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1863 saved_seconds
= yourtm
.tm_sec
;
1864 yourtm
.tm_sec
= SECSPERMIN
- 1;
1866 saved_seconds
= yourtm
.tm_sec
;
1870 ** Do a binary search (this works whatever time_t's type is).
1872 /* LINTED constant */
1873 if (!TYPE_SIGNED(time_t)) {
1876 /* LINTED constant */
1877 } else if (!TYPE_INTEGRAL(time_t)) {
1879 if (sizeof(time_t) > sizeof(float))
1880 /* LINTED assumed double */
1881 hi
= (time_t) DBL_MAX
;
1882 /* LINTED assumed float */
1883 else hi
= (time_t) FLT_MAX
;
1887 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
1891 #ifdef NO_ERROR_IN_DST_GAP
1895 t
= lo
/ 2 + hi
/ 2;
1900 if ((*funcp
)(sp
, &t
, offset
, &mytm
) == NULL
) {
1902 ** Assume that t is too extreme to be represented in
1903 ** a struct tm; arrange things so that it is less
1904 ** extreme on the next pass.
1906 dir
= (t
> 0) ? 1 : -1;
1907 } else dir
= tmcomp(&mytm
, &yourtm
);
1914 } else if (t
== hi
) {
1920 #ifdef NO_ERROR_IN_DST_GAP
1921 if (ilo
!= lo
&& lo
- 1 == hi
&& yourtm
.tm_isdst
< 0 &&
1923 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1924 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1926 if (sp
->ttis
[j
].tt_isdst
==
1927 sp
->ttis
[i
].tt_isdst
)
1929 off
= sp
->ttis
[j
].tt_gmtoff
-
1930 sp
->ttis
[i
].tt_gmtoff
;
1931 yourtm
.tm_sec
+= off
< 0 ?
1945 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1948 ** Right time, wrong type.
1949 ** Hunt for right time, right type.
1950 ** It's okay to guess wrong since the guess
1955 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1956 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1958 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1959 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
1961 newt
= (time_t)(t
+ sp
->ttis
[j
].tt_gmtoff
-
1962 sp
->ttis
[i
].tt_gmtoff
);
1963 if ((*funcp
)(sp
, &newt
, offset
, &mytm
) == NULL
)
1965 if (tmcomp(&mytm
, &yourtm
) != 0)
1967 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
1979 newt
= t
+ saved_seconds
;
1980 if ((newt
< t
) != (saved_seconds
< 0))
1983 if ((*funcp
)(sp
, &t
, offset
, tmp
)) {
1996 time2(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
1997 const long offset
, int *const okayp
)
2002 ** First try without normalization of seconds
2003 ** (in case tm_sec contains a value associated with a leap second).
2004 ** If that fails, try with normalization of seconds.
2006 t
= time2sub(sp
, tmp
, funcp
, offset
, okayp
, FALSE
);
2007 return *okayp
? t
: time2sub(sp
, tmp
, funcp
, offset
, okayp
, TRUE
);
2011 time1(const timezone_t sp
, struct tm
*const tmp
, subfun_t funcp
,
2016 int sameind
, otherind
;
2019 int seen
[TZ_MAX_TYPES
];
2020 int types
[TZ_MAX_TYPES
];
2027 if (tmp
->tm_isdst
> 1)
2029 t
= time2(sp
, tmp
, funcp
, offset
, &okay
);
2032 ** PCTS code courtesy Grant Sullivan.
2036 if (tmp
->tm_isdst
< 0)
2037 tmp
->tm_isdst
= 0; /* reset to std and try again */
2038 #endif /* defined PCTS */
2040 if (okay
|| tmp
->tm_isdst
< 0)
2042 #endif /* !defined PCTS */
2044 ** We're supposed to assume that somebody took a time of one type
2045 ** and did some math on it that yielded a "struct tm" that's bad.
2046 ** We try to divine the type they started from and adjust to the
2053 for (i
= 0; i
< sp
->typecnt
; ++i
)
2056 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
2057 if (!seen
[sp
->types
[i
]]) {
2058 seen
[sp
->types
[i
]] = TRUE
;
2059 types
[nseen
++] = sp
->types
[i
];
2061 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2062 samei
= types
[sameind
];
2063 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2065 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2066 otheri
= types
[otherind
];
2067 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
2069 tmp
->tm_sec
+= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2070 sp
->ttis
[samei
].tt_gmtoff
);
2071 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2072 t
= time2(sp
, tmp
, funcp
, offset
, &okay
);
2075 tmp
->tm_sec
-= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2076 sp
->ttis
[samei
].tt_gmtoff
);
2077 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2085 mktime_z(const timezone_t sp
, struct tm
*tmp
)
2089 t
= time1(NULL
, tmp
, gmtsub
, 0L);
2091 t
= time1(sp
, tmp
, localsub
, 0L);
2096 mktime(struct tm
* const tmp
)
2100 rwlock_wrlock(&lcl_lock
);
2102 result
= mktime_z(lclptr
, tmp
);
2103 rwlock_unlock(&lcl_lock
);
2110 timelocal_z(const timezone_t sp
, struct tm
*tmp
)
2113 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2114 return mktime_z(sp
, tmp
);
2118 timelocal(struct tm
*const tmp
)
2121 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2126 timegm(struct tm
*const tmp
)
2132 t
= time1(gmtptr
, tmp
, gmtsub
, 0L);
2137 timeoff(struct tm
*const tmp
, const long offset
)
2143 t
= time1(gmtptr
, tmp
, gmtsub
, offset
);
2147 #endif /* defined STD_INSPIRED */
2152 ** The following is supplied for compatibility with
2153 ** previous versions of the CMUCS runtime library.
2157 gtime(struct tm
*const tmp
)
2159 const time_t t
= mktime(tmp
);
2166 #endif /* defined CMUCS */
2169 ** XXX--is the below the right way to conditionalize??
2175 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2176 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2177 ** is not the case if we are accounting for leap seconds.
2178 ** So, we provide the following conversion routines for use
2179 ** when exchanging timestamps with POSIX conforming systems.
2183 leapcorr(const timezone_t sp
, time_t *timep
)
2191 if (*timep
>= lp
->ls_trans
)
2198 time2posix_z(const timezone_t sp
, time_t t
)
2200 return (time_t)(t
- leapcorr(sp
, &t
));
2204 time2posix(time_t t
)
2207 rwlock_wrlock(&lcl_lock
);
2209 result
= (time_t)(t
- leapcorr(lclptr
, &t
));
2210 rwlock_unlock(&lcl_lock
);
2215 posix2time_z(const timezone_t sp
, time_t t
)
2221 ** For a positive leap second hit, the result
2222 ** is not unique. For a negative leap second
2223 ** hit, the corresponding time doesn't exist,
2224 ** so we return an adjacent second.
2226 x
= (time_t)(t
+ leapcorr(sp
, &t
));
2227 y
= (time_t)(x
- leapcorr(sp
, &x
));
2231 y
= (time_t)(x
- leapcorr(sp
, &x
));
2239 y
= (time_t)(x
- leapcorr(sp
, &x
));
2251 posix2time(time_t t
)
2255 rwlock_wrlock(&lcl_lock
);
2257 result
= posix2time_z(lclptr
, t
);
2258 rwlock_unlock(&lcl_lock
);
2262 #endif /* defined STD_INSPIRED */
2264 #if defined(__minix) && defined(__weak_alias)
2265 __weak_alias(gmtime
, __gmtime50
)
2266 __weak_alias(gmtime_r
, __gmtime_r50
)
2267 __weak_alias(offtime
, __offtime50
)
2268 __weak_alias(offtime_r
, __offtime_r50
)
2269 __weak_alias(time2posix
, __time2posix50
)
2270 __weak_alias(time2posix_z
, __time2posix_z50
)
2271 __weak_alias(timegm
, __timegm50
)
2272 __weak_alias(timelocal
, __timelocal50
)
2273 __weak_alias(timelocal_z
, __timelocal_z50
)
2274 __weak_alias(timeoff
, __timeoff50
)
2275 __weak_alias(tzalloc
, __tzalloc50
)
2276 __weak_alias(tzfree
, __tzfree50
)
2277 __weak_alias(tzgetname
, __tzgetname50
)
2278 __weak_alias(tzset
, __tzset50
)
2279 __weak_alias(tzsetwall
, __tzsetwall50
)