1 /* $NetBSD: localtime.c,v 1.44 2009/10/24 17:01:04 mlelstv 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.9";
13 __RCSID("$NetBSD: localtime.c,v 1.44 2009/10/24 17:01:04 mlelstv 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
)
33 __weak_alias(tzset
,_tzset
)
34 __weak_alias(tzsetwall
,_tzsetwall
)
37 #include "float.h" /* for FLT_MAX and DBL_MAX */
39 #ifndef TZ_ABBR_MAX_LEN
40 #define TZ_ABBR_MAX_LEN 16
41 #endif /* !defined TZ_ABBR_MAX_LEN */
43 #ifndef TZ_ABBR_CHAR_SET
44 #define TZ_ABBR_CHAR_SET \
45 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
46 #endif /* !defined TZ_ABBR_CHAR_SET */
48 #ifndef TZ_ABBR_ERR_CHAR
49 #define TZ_ABBR_ERR_CHAR '_'
50 #endif /* !defined TZ_ABBR_ERR_CHAR */
53 ** SunOS 4.1.1 headers lack O_BINARY.
57 #define OPEN_MODE (O_RDONLY | O_BINARY)
58 #endif /* defined O_BINARY */
60 #define OPEN_MODE O_RDONLY
61 #endif /* !defined O_BINARY */
65 ** Someone might make incorrect use of a time zone abbreviation:
66 ** 1. They might reference tzname[0] before calling tzset (explicitly
68 ** 2. They might reference tzname[1] before calling tzset (explicitly
70 ** 3. They might reference tzname[1] after setting to a time zone
71 ** in which Daylight Saving Time is never observed.
72 ** 4. They might reference tzname[0] after setting to a time zone
73 ** in which Standard Time is never observed.
74 ** 5. They might reference tm.TM_ZONE after calling offtime.
75 ** What's best to do in the above cases is open to debate;
76 ** for now, we just set things up so that in any of the five cases
77 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
78 ** string "tzname[0] used before set", and similarly for the other cases.
79 ** And another: initialize tzname[0] to "ERA", with an explanation in the
80 ** manual page of what this "time zone abbreviation" means (doing this so
81 ** that tzname[0] has the "normal" length of three characters).
84 #endif /* !defined WILDABBR */
86 static const char wildabbr
[] = WILDABBR
;
88 static const char gmt
[] = "GMT";
91 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
92 ** We default to US rules as of 1999-08-17.
93 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
94 ** implementation dependent; for historical reasons, US rules are a
97 #ifndef TZDEFRULESTRING
98 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
99 #endif /* !defined TZDEFDST */
101 struct ttinfo
{ /* time type information */
102 long tt_gmtoff
; /* UTC offset in seconds */
103 int tt_isdst
; /* used to set tm_isdst */
104 int tt_abbrind
; /* abbreviation list index */
105 int tt_ttisstd
; /* TRUE if transition is std time */
106 int tt_ttisgmt
; /* TRUE if transition is UTC */
109 struct lsinfo
{ /* leap second information */
110 time_t ls_trans
; /* transition time */
111 long ls_corr
; /* correction to apply */
114 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
117 #define MY_TZNAME_MAX TZNAME_MAX
118 #endif /* defined TZNAME_MAX */
120 #define MY_TZNAME_MAX 255
121 #endif /* !defined TZNAME_MAX */
130 time_t ats
[TZ_MAX_TIMES
];
131 unsigned char types
[TZ_MAX_TIMES
];
132 struct ttinfo ttis
[TZ_MAX_TYPES
];
133 char chars
[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
134 (2 * (MY_TZNAME_MAX
+ 1)))];
135 struct lsinfo lsis
[TZ_MAX_LEAPS
];
139 int r_type
; /* type of rule--see below */
140 int r_day
; /* day number of rule */
141 int r_week
; /* week number of rule */
142 int r_mon
; /* month number of rule */
143 long r_time
; /* transition time of rule */
146 #define JULIAN_DAY 0 /* Jn - Julian day */
147 #define DAY_OF_YEAR 1 /* n - day of year */
148 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
151 ** Prototypes for static functions.
154 static long detzcode(const char * codep
);
155 static time_t detzcode64(const char * codep
);
156 static int differ_by_repeat(time_t t1
, time_t t0
);
157 static const char * getzname(const char * strp
);
158 static const char * getqzname(const char * strp
, const int delim
);
159 static const char * getnum(const char * strp
, int * nump
, int min
,
161 static const char * getsecs(const char * strp
, long * secsp
);
162 static const char * getoffset(const char * strp
, long * offsetp
);
163 static const char * getrule(const char * strp
, struct rule
* rulep
);
164 static void gmtload(struct state
* sp
);
165 static struct tm
* gmtsub(const time_t * timep
, long offset
,
167 static struct tm
* localsub(const time_t * timep
, long offset
,
169 static int increment_overflow(int * number
, int delta
);
170 static int leaps_thru_end_of(int y
);
171 static int long_increment_overflow(long * number
, int delta
);
172 static int long_normalize_overflow(long * tensptr
,
173 int * unitsptr
, int base
);
174 static int normalize_overflow(int * tensptr
, int * unitsptr
,
176 static void settzname(void);
177 static time_t time1(struct tm
* tmp
,
178 struct tm
* (*funcp
)(const time_t *,
181 static time_t time2(struct tm
*tmp
,
182 struct tm
* (*funcp
)(const time_t *,
184 long offset
, int * okayp
);
185 static time_t time2sub(struct tm
*tmp
,
186 struct tm
* (*funcp
)(const time_t *,
188 long offset
, int * okayp
, int do_norm_secs
);
189 static struct tm
* timesub(const time_t * timep
, long offset
,
190 const struct state
* sp
, struct tm
* tmp
);
191 static int tmcomp(const struct tm
* atmp
,
192 const struct tm
* btmp
);
193 static time_t transtime(time_t janfirst
, int year
,
194 const struct rule
* rulep
, long offset
);
195 static int typesequiv(const struct state
* sp
, int a
, int b
);
196 static int tzload(const char * name
, struct state
* sp
,
198 static int tzparse(const char * name
, struct state
* sp
,
200 static void tzset_unlocked(void);
201 static void tzsetwall_unlocked(void);
202 static long leapcorr(time_t * timep
);
205 static struct state
* lclptr
;
206 static struct state
* gmtptr
;
207 #endif /* defined ALL_STATE */
210 static struct state lclmem
;
211 static struct state gmtmem
;
212 #define lclptr (&lclmem)
213 #define gmtptr (&gmtmem)
214 #endif /* State Farm */
216 #ifndef TZ_STRLEN_MAX
217 #define TZ_STRLEN_MAX 255
218 #endif /* !defined TZ_STRLEN_MAX */
220 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
221 static int lcl_is_set
;
222 static int gmt_is_set
;
224 #if !defined(__LIBC12_SOURCE__)
226 __aconst
char * tzname
[2] = {
227 (__aconst
char *)__UNCONST(wildabbr
),
228 (__aconst
char *)__UNCONST(wildabbr
)
233 extern __aconst
char * tzname
[2];
238 static rwlock_t lcl_lock
= RWLOCK_INITIALIZER
;
242 ** Section 4.12.3 of X3.159-1989 requires that
243 ** Except for the strftime function, these functions [asctime,
244 ** ctime, gmtime, localtime] return values in one of two static
245 ** objects: a broken-down time structure and an array of char.
246 ** Thanks to Paul Eggert for noting this.
252 #if !defined(__LIBC12_SOURCE__)
257 extern long timezone
__RENAME(__timezone13
);
259 #endif /* defined USG_COMPAT */
263 #endif /* defined ALTZONE */
267 const char * const codep
;
269 register long result
;
272 result
= (codep
[0] & 0x80) ? ~0L : 0;
273 for (i
= 0; i
< 4; ++i
)
274 result
= (result
<< 8) | (codep
[i
] & 0xff);
280 const char * const codep
;
282 register time_t result
;
285 result
= (codep
[0] & 0x80) ? -1 : 0;
286 for (i
= 0; i
< 8; ++i
)
287 result
= result
* 256 + (codep
[i
] & 0xff);
294 register struct state
* const sp
= lclptr
;
297 tzname
[0] = (__aconst
char *)__UNCONST(wildabbr
);
298 tzname
[1] = (__aconst
char *)__UNCONST(wildabbr
);
302 #endif /* defined USG_COMPAT */
305 #endif /* defined ALTZONE */
308 tzname
[0] = tzname
[1] = (__aconst
char *)__UNCONST(gmt
);
311 #endif /* defined ALL_STATE */
312 for (i
= 0; i
< sp
->typecnt
; ++i
) {
313 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
315 tzname
[ttisp
->tt_isdst
] =
316 &sp
->chars
[ttisp
->tt_abbrind
];
320 if (i
== 0 || !ttisp
->tt_isdst
)
321 timezone
= -(ttisp
->tt_gmtoff
);
322 #endif /* defined USG_COMPAT */
324 if (i
== 0 || ttisp
->tt_isdst
)
325 altzone
= -(ttisp
->tt_gmtoff
);
326 #endif /* defined ALTZONE */
329 ** And to get the latest zone names into tzname. . .
331 for (i
= 0; i
< sp
->timecnt
; ++i
) {
332 register const struct ttinfo
* const ttisp
=
336 tzname
[ttisp
->tt_isdst
] =
337 &sp
->chars
[ttisp
->tt_abbrind
];
340 ** Finally, scrub the abbreviations.
341 ** First, replace bogus characters.
343 for (i
= 0; i
< sp
->charcnt
; ++i
)
344 if (strchr(TZ_ABBR_CHAR_SET
, sp
->chars
[i
]) == NULL
)
345 sp
->chars
[i
] = TZ_ABBR_ERR_CHAR
;
347 ** Second, truncate long abbreviations.
349 for (i
= 0; i
< sp
->typecnt
; ++i
) {
350 register const struct ttinfo
* const ttisp
= &sp
->ttis
[i
];
351 register char * cp
= &sp
->chars
[ttisp
->tt_abbrind
];
353 if (strlen(cp
) > TZ_ABBR_MAX_LEN
&&
354 strcmp(cp
, GRANDPARENTED
) != 0)
355 *(cp
+ TZ_ABBR_MAX_LEN
) = '\0';
360 differ_by_repeat(t1
, t0
)
365 if (TYPE_INTEGRAL(time_t) &&
366 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS
)
368 return (int_fast64_t)t1
- (int_fast64_t)t0
== SECSPERREPEAT
;
372 tzload(name
, sp
, doextend
)
373 register const char * name
;
374 register struct state
* const sp
;
375 register const int doextend
;
377 register const char * p
;
383 struct tzhead tzhead
;
384 char buf
[2 * sizeof(struct tzhead
) +
389 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
392 register int doaccess
;
394 ** Section 4.9.1 of the C standard says that
395 ** "FILENAME_MAX expands to an integral constant expression
396 ** that is the size needed for an array of char large enough
397 ** to hold the longest file name string that the implementation
398 ** guarantees can be opened."
400 char fullname
[FILENAME_MAX
+ 1];
404 doaccess
= name
[0] == '/';
406 if ((p
= TZDIR
) == NULL
)
408 if ((strlen(p
) + strlen(name
) + 1) >= sizeof fullname
)
410 (void) strcpy(fullname
, p
); /* XXX strcpy is safe */
411 (void) strcat(fullname
, "/"); /* XXX strcat is safe */
412 (void) strcat(fullname
, name
); /* XXX strcat is safe */
414 ** Set doaccess if '.' (as in "../") shows up in name.
416 if (strchr(name
, '.') != NULL
)
420 if (doaccess
&& access(name
, R_OK
) != 0)
423 * XXX potential security problem here if user of a set-id
424 * program has set TZ (which is passed in as name) here,
425 * and uses a race condition trick to defeat the access(2)
428 if ((fid
= open(name
, OPEN_MODE
)) == -1)
431 nread
= read(fid
, u
.buf
, sizeof u
.buf
);
432 if (close(fid
) < 0 || nread
<= 0)
434 for (stored
= 4; stored
<= 8; stored
*= 2) {
438 ttisstdcnt
= (int) detzcode(u
.tzhead
.tzh_ttisstdcnt
);
439 ttisgmtcnt
= (int) detzcode(u
.tzhead
.tzh_ttisgmtcnt
);
440 sp
->leapcnt
= (int) detzcode(u
.tzhead
.tzh_leapcnt
);
441 sp
->timecnt
= (int) detzcode(u
.tzhead
.tzh_timecnt
);
442 sp
->typecnt
= (int) detzcode(u
.tzhead
.tzh_typecnt
);
443 sp
->charcnt
= (int) detzcode(u
.tzhead
.tzh_charcnt
);
444 p
= u
.tzhead
.tzh_charcnt
+ sizeof u
.tzhead
.tzh_charcnt
;
445 if (sp
->leapcnt
< 0 || sp
->leapcnt
> TZ_MAX_LEAPS
||
446 sp
->typecnt
<= 0 || sp
->typecnt
> TZ_MAX_TYPES
||
447 sp
->timecnt
< 0 || sp
->timecnt
> TZ_MAX_TIMES
||
448 sp
->charcnt
< 0 || sp
->charcnt
> TZ_MAX_CHARS
||
449 (ttisstdcnt
!= sp
->typecnt
&& ttisstdcnt
!= 0) ||
450 (ttisgmtcnt
!= sp
->typecnt
&& ttisgmtcnt
!= 0))
452 if (nread
- (p
- u
.buf
) <
453 sp
->timecnt
* stored
+ /* ats */
454 sp
->timecnt
+ /* types */
455 sp
->typecnt
* 6 + /* ttinfos */
456 sp
->charcnt
+ /* chars */
457 sp
->leapcnt
* (stored
+ 4) + /* lsinfos */
458 ttisstdcnt
+ /* ttisstds */
459 ttisgmtcnt
) /* ttisgmts */
461 for (i
= 0; i
< sp
->timecnt
; ++i
) {
462 sp
->ats
[i
] = (stored
== 4) ?
463 detzcode(p
) : detzcode64(p
);
466 for (i
= 0; i
< sp
->timecnt
; ++i
) {
467 sp
->types
[i
] = (unsigned char) *p
++;
468 if (sp
->types
[i
] >= sp
->typecnt
)
471 for (i
= 0; i
< sp
->typecnt
; ++i
) {
472 register struct ttinfo
* ttisp
;
474 ttisp
= &sp
->ttis
[i
];
475 ttisp
->tt_gmtoff
= detzcode(p
);
477 ttisp
->tt_isdst
= (unsigned char) *p
++;
478 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
480 ttisp
->tt_abbrind
= (unsigned char) *p
++;
481 if (ttisp
->tt_abbrind
< 0 ||
482 ttisp
->tt_abbrind
> sp
->charcnt
)
485 for (i
= 0; i
< sp
->charcnt
; ++i
)
487 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
488 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
489 register struct lsinfo
* lsisp
;
491 lsisp
= &sp
->lsis
[i
];
492 lsisp
->ls_trans
= (stored
== 4) ?
493 detzcode(p
) : detzcode64(p
);
495 lsisp
->ls_corr
= detzcode(p
);
498 for (i
= 0; i
< sp
->typecnt
; ++i
) {
499 register struct ttinfo
* ttisp
;
501 ttisp
= &sp
->ttis
[i
];
503 ttisp
->tt_ttisstd
= FALSE
;
505 ttisp
->tt_ttisstd
= *p
++;
506 if (ttisp
->tt_ttisstd
!= TRUE
&&
507 ttisp
->tt_ttisstd
!= FALSE
)
511 for (i
= 0; i
< sp
->typecnt
; ++i
) {
512 register struct ttinfo
* ttisp
;
514 ttisp
= &sp
->ttis
[i
];
516 ttisp
->tt_ttisgmt
= FALSE
;
518 ttisp
->tt_ttisgmt
= *p
++;
519 if (ttisp
->tt_ttisgmt
!= TRUE
&&
520 ttisp
->tt_ttisgmt
!= FALSE
)
525 ** Out-of-sort ats should mean we're running on a
526 ** signed time_t system but using a data file with
527 ** unsigned values (or vice versa).
529 for (i
= 0; i
< sp
->timecnt
- 2; ++i
)
530 if (sp
->ats
[i
] > sp
->ats
[i
+ 1]) {
533 if (TYPE_SIGNED(time_t)) {
535 ** Ignore the end (easy).
540 ** Ignore the beginning (harder).
544 for (j
= 0; j
+ i
< sp
->timecnt
; ++j
) {
545 sp
->ats
[j
] = sp
->ats
[j
+ i
];
546 sp
->types
[j
] = sp
->types
[j
+ i
];
553 ** If this is an old file, we're done.
555 if (u
.tzhead
.tzh_version
[0] == '\0')
558 for (i
= 0; i
< nread
; ++i
)
561 ** If this is a narrow integer time_t system, we're done.
563 if (stored
>= (int) sizeof(time_t)
565 && TYPE_INTEGRAL(time_t))
568 if (doextend
&& nread
> 2 &&
569 u
.buf
[0] == '\n' && u
.buf
[nread
- 1] == '\n' &&
570 sp
->typecnt
+ 2 <= TZ_MAX_TYPES
) {
574 u
.buf
[nread
- 1] = '\0';
575 result
= tzparse(&u
.buf
[1], &ts
, FALSE
);
576 if (result
== 0 && ts
.typecnt
== 2 &&
577 sp
->charcnt
+ ts
.charcnt
<= TZ_MAX_CHARS
) {
578 for (i
= 0; i
< 2; ++i
)
579 ts
.ttis
[i
].tt_abbrind
+=
581 for (i
= 0; i
< ts
.charcnt
; ++i
)
582 sp
->chars
[sp
->charcnt
++] =
585 while (i
< ts
.timecnt
&&
587 sp
->ats
[sp
->timecnt
- 1])
589 while (i
< ts
.timecnt
&&
590 sp
->timecnt
< TZ_MAX_TIMES
) {
591 sp
->ats
[sp
->timecnt
] =
593 sp
->types
[sp
->timecnt
] =
599 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[0];
600 sp
->ttis
[sp
->typecnt
++] = ts
.ttis
[1];
603 sp
->goback
= sp
->goahead
= FALSE
;
604 if (sp
->timecnt
> 1) {
605 for (i
= 1; i
< sp
->timecnt
; ++i
)
606 if (typesequiv(sp
, sp
->types
[i
], sp
->types
[0]) &&
607 differ_by_repeat(sp
->ats
[i
], sp
->ats
[0])) {
611 for (i
= sp
->timecnt
- 2; i
>= 0; --i
)
612 if (typesequiv(sp
, sp
->types
[sp
->timecnt
- 1],
614 differ_by_repeat(sp
->ats
[sp
->timecnt
- 1],
625 const struct state
* const sp
;
632 a
< 0 || a
>= sp
->typecnt
||
633 b
< 0 || b
>= sp
->typecnt
)
636 register const struct ttinfo
* ap
= &sp
->ttis
[a
];
637 register const struct ttinfo
* bp
= &sp
->ttis
[b
];
638 result
= ap
->tt_gmtoff
== bp
->tt_gmtoff
&&
639 ap
->tt_isdst
== bp
->tt_isdst
&&
640 ap
->tt_ttisstd
== bp
->tt_ttisstd
&&
641 ap
->tt_ttisgmt
== bp
->tt_ttisgmt
&&
642 strcmp(&sp
->chars
[ap
->tt_abbrind
],
643 &sp
->chars
[bp
->tt_abbrind
]) == 0;
648 static const int mon_lengths
[2][MONSPERYEAR
] = {
649 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
650 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
653 static const int year_lengths
[2] = {
654 DAYSPERNYEAR
, DAYSPERLYEAR
658 ** Given a pointer into a time zone string, scan until a character that is not
659 ** a valid character in a zone name is found. Return a pointer to that
665 register const char * strp
;
669 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
676 ** Given a pointer into an extended time zone string, scan until the ending
677 ** delimiter of the zone name is located. Return a pointer to the delimiter.
679 ** As with getzname above, the legal character set is actually quite
680 ** restricted, with other characters producing undefined results.
681 ** We don't do any checking here; checking is done later in common-case code.
685 getqzname(register const char *strp
, const int delim
)
689 while ((c
= *strp
) != '\0' && c
!= delim
)
695 ** Given a pointer into a time zone string, extract a number from that string.
696 ** Check that the number is within a specified range; if it is not, return
698 ** Otherwise, return a pointer to the first character not part of the number.
702 getnum(strp
, nump
, min
, max
)
703 register const char * strp
;
711 if (strp
== NULL
|| !is_digit(c
= *strp
))
715 num
= num
* 10 + (c
- '0');
717 return NULL
; /* illegal value */
719 } while (is_digit(c
));
721 return NULL
; /* illegal value */
727 ** Given a pointer into a time zone string, extract a number of seconds,
728 ** in hh[:mm[:ss]] form, from the string.
729 ** If any error occurs, return NULL.
730 ** Otherwise, return a pointer to the first character not part of the number
736 register const char * strp
;
742 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
743 ** "M10.4.6/26", which does not conform to Posix,
744 ** but which specifies the equivalent of
745 ** ``02:00 on the first Sunday on or after 23 Oct''.
747 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
750 *secsp
= num
* (long) SECSPERHOUR
;
753 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
756 *secsp
+= num
* SECSPERMIN
;
759 /* `SECSPERMIN' allows for leap seconds. */
760 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
770 ** Given a pointer into a time zone string, extract an offset, in
771 ** [+-]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 time.
777 getoffset(strp
, offsetp
)
778 register const char * strp
;
779 long * const offsetp
;
781 register int neg
= 0;
786 } else if (*strp
== '+')
788 strp
= getsecs(strp
, offsetp
);
790 return NULL
; /* illegal time */
792 *offsetp
= -*offsetp
;
797 ** Given a pointer into a time zone string, extract a rule in the form
798 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
799 ** If a valid rule is not found, return NULL.
800 ** Otherwise, return a pointer to the first character not part of the rule.
806 register struct rule
* const rulep
;
812 rulep
->r_type
= JULIAN_DAY
;
814 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
815 } else if (*strp
== 'M') {
819 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
821 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
826 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
831 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
832 } else if (is_digit(*strp
)) {
836 rulep
->r_type
= DAY_OF_YEAR
;
837 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
838 } else return NULL
; /* invalid format */
846 strp
= getsecs(strp
, &rulep
->r_time
);
847 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
852 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
853 ** year, a rule, and the offset from UTC at the time that rule takes effect,
854 ** calculate the Epoch-relative time that rule takes effect.
858 transtime(janfirst
, year
, rulep
, offset
)
859 const time_t janfirst
;
861 register const struct rule
* const rulep
;
864 register int leapyear
;
865 register time_t value
;
867 int d
, m1
, yy0
, yy1
, yy2
, dow
;
870 leapyear
= isleap(year
);
871 switch (rulep
->r_type
) {
875 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
877 ** In non-leap years, or if the day number is 59 or less, just
878 ** add SECSPERDAY times the day number-1 to the time of
879 ** January 1, midnight, to get the day.
881 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
882 if (leapyear
&& rulep
->r_day
>= 60)
889 ** Just add SECSPERDAY times the day number to the time of
890 ** January 1, midnight, to get the day.
892 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
895 case MONTH_NTH_DAY_OF_WEEK
:
897 ** Mm.n.d - nth "dth day" of month m.
900 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
901 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
904 ** Use Zeller's Congruence to get day-of-week of first day of
907 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
908 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
911 dow
= ((26 * m1
- 2) / 10 +
912 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
917 ** "dow" is the day-of-week of the first day of the month. Get
918 ** the day-of-month (zero-origin) of the first "dow" day of the
921 d
= rulep
->r_day
- dow
;
924 for (i
= 1; i
< rulep
->r_week
; ++i
) {
925 if (d
+ DAYSPERWEEK
>=
926 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
932 ** "d" is the day-of-month (zero-origin) of the day we want.
934 value
+= d
* SECSPERDAY
;
939 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
940 ** question. To get the Epoch-relative time of the specified local
941 ** time on that day, add the transition time and the current offset
944 return value
+ rulep
->r_time
+ offset
;
948 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
953 tzparse(name
, sp
, lastditch
)
955 register struct state
* const sp
;
958 const char * stdname
;
959 const char * dstname
;
964 register time_t * atp
;
965 register unsigned char * typep
;
967 register int load_result
;
972 stdlen
= strlen(name
); /* length of standard zone name */
974 if (stdlen
>= sizeof sp
->chars
)
975 stdlen
= (sizeof sp
->chars
) - 1;
981 name
= getqzname(name
, '>');
984 stdlen
= name
- stdname
;
987 name
= getzname(name
);
988 stdlen
= name
- stdname
;
992 name
= getoffset(name
, &stdoffset
);
996 load_result
= tzload(TZDEFRULES
, sp
, FALSE
);
997 if (load_result
!= 0)
998 sp
->leapcnt
= 0; /* so, we're off a little */
1002 name
= getqzname(name
, '>');
1005 dstlen
= name
- dstname
;
1009 name
= getzname(name
);
1010 dstlen
= name
- dstname
; /* length of DST zone name */
1012 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1013 name
= getoffset(name
, &dstoffset
);
1016 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1017 if (*name
== '\0' && load_result
!= 0)
1018 name
= TZDEFRULESTRING
;
1019 if (*name
== ',' || *name
== ';') {
1023 register time_t janfirst
;
1028 if ((name
= getrule(name
, &start
)) == NULL
)
1032 if ((name
= getrule(name
, &end
)) == NULL
)
1036 sp
->typecnt
= 2; /* standard time and DST */
1038 ** Two transitions per year, from EPOCH_YEAR forward.
1040 sp
->ttis
[0].tt_gmtoff
= -dstoffset
;
1041 sp
->ttis
[0].tt_isdst
= 1;
1042 sp
->ttis
[0].tt_abbrind
= stdlen
+ 1;
1043 sp
->ttis
[1].tt_gmtoff
= -stdoffset
;
1044 sp
->ttis
[1].tt_isdst
= 0;
1045 sp
->ttis
[1].tt_abbrind
= 0;
1050 for (year
= EPOCH_YEAR
;
1051 sp
->timecnt
+ 2 <= TZ_MAX_TIMES
;
1055 starttime
= transtime(janfirst
, year
, &start
,
1057 endtime
= transtime(janfirst
, year
, &end
,
1059 if (starttime
> endtime
) {
1061 *typep
++ = 1; /* DST ends */
1063 *typep
++ = 0; /* DST begins */
1066 *typep
++ = 0; /* DST begins */
1068 *typep
++ = 1; /* DST ends */
1071 newfirst
= janfirst
;
1072 newfirst
+= year_lengths
[isleap(year
)] *
1074 if (newfirst
<= janfirst
)
1076 janfirst
= newfirst
;
1079 register long theirstdoffset
;
1080 register long theirdstoffset
;
1081 register long theiroffset
;
1089 ** Initial values of theirstdoffset
1092 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1094 if (!sp
->ttis
[j
].tt_isdst
) {
1096 -sp
->ttis
[j
].tt_gmtoff
;
1101 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1103 if (sp
->ttis
[j
].tt_isdst
) {
1105 -sp
->ttis
[j
].tt_gmtoff
;
1110 ** Initially we're assumed to be in standard time.
1113 theiroffset
= theirstdoffset
;
1115 ** Now juggle transition times and types
1116 ** tracking offsets as you do.
1118 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1120 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1121 if (sp
->ttis
[j
].tt_ttisgmt
) {
1122 /* No adjustment to transition time */
1125 ** If summer time is in effect, and the
1126 ** transition time was not specified as
1127 ** standard time, add the summer time
1128 ** offset to the transition time;
1129 ** otherwise, add the standard time
1130 ** offset to the transition time.
1133 ** Transitions from DST to DDST
1134 ** will effectively disappear since
1135 ** POSIX provides for only one DST
1138 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1139 sp
->ats
[i
] += dstoffset
-
1142 sp
->ats
[i
] += stdoffset
-
1146 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1147 if (!sp
->ttis
[j
].tt_isdst
)
1148 theirstdoffset
= theiroffset
;
1149 else theirdstoffset
= theiroffset
;
1152 ** Finally, fill in ttis.
1153 ** ttisstd and ttisgmt need not be handled.
1155 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1156 sp
->ttis
[0].tt_isdst
= FALSE
;
1157 sp
->ttis
[0].tt_abbrind
= 0;
1158 sp
->ttis
[1].tt_gmtoff
= -dstoffset
;
1159 sp
->ttis
[1].tt_isdst
= TRUE
;
1160 sp
->ttis
[1].tt_abbrind
= stdlen
+ 1;
1165 sp
->typecnt
= 1; /* only standard time */
1167 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1168 sp
->ttis
[0].tt_isdst
= 0;
1169 sp
->ttis
[0].tt_abbrind
= 0;
1171 sp
->charcnt
= stdlen
+ 1;
1173 sp
->charcnt
+= dstlen
+ 1;
1174 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1177 (void) strncpy(cp
, stdname
, stdlen
);
1181 (void) strncpy(cp
, dstname
, dstlen
);
1182 *(cp
+ dstlen
) = '\0';
1189 struct state
* const sp
;
1191 if (tzload(gmt
, sp
, TRUE
) != 0)
1192 (void) tzparse(gmt
, sp
, TRUE
);
1196 tzsetwall_unlocked(void)
1203 if (lclptr
== NULL
) {
1204 int saveerrno
= errno
;
1205 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1207 if (lclptr
== NULL
) {
1208 settzname(); /* all we can do */
1212 #endif /* defined ALL_STATE */
1213 if (tzload((char *) NULL
, lclptr
, TRUE
) != 0)
1218 #ifndef STD_INSPIRED
1220 ** A non-static declaration of tzsetwall in a system header file
1221 ** may cause a warning about this upcoming static declaration...
1224 #endif /* !defined STD_INSPIRED */
1228 rwlock_wrlock(&lcl_lock
);
1229 tzsetwall_unlocked();
1230 rwlock_unlock(&lcl_lock
);
1233 #ifndef STD_INSPIRED
1235 ** A non-static declaration of tzsetwall in a system header file
1236 ** may cause a warning about this upcoming static declaration...
1239 #endif /* !defined STD_INSPIRED */
1241 tzset_unlocked(void)
1243 register const char * name
;
1247 name
= getenv("TZ");
1250 tzsetwall_unlocked();
1254 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0)
1256 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1258 (void)strlcpy(lcl_TZname
, name
, sizeof(lcl_TZname
));
1261 if (lclptr
== NULL
) {
1263 lclptr
= (struct state
*) malloc(sizeof *lclptr
);
1265 if (lclptr
== NULL
) {
1266 settzname(); /* all we can do */
1270 #endif /* defined ALL_STATE */
1271 if (*name
== '\0') {
1273 ** User wants it fast rather than right.
1275 lclptr
->leapcnt
= 0; /* so, we're off a little */
1276 lclptr
->timecnt
= 0;
1277 lclptr
->typecnt
= 0;
1278 lclptr
->ttis
[0].tt_isdst
= 0;
1279 lclptr
->ttis
[0].tt_gmtoff
= 0;
1280 lclptr
->ttis
[0].tt_abbrind
= 0;
1281 (void) strlcpy(lclptr
->chars
, gmt
, sizeof(lclptr
->chars
));
1282 } else if (tzload(name
, lclptr
, TRUE
) != 0)
1283 if (name
[0] == ':' || tzparse(name
, lclptr
, FALSE
) != 0)
1284 (void) gmtload(lclptr
);
1291 rwlock_wrlock(&lcl_lock
);
1293 rwlock_unlock(&lcl_lock
);
1297 ** The easy way to behave "as if no library function calls" localtime
1298 ** is to not call it--so we drop its guts into "localsub", which can be
1299 ** freely called. (And no, the PANS doesn't require the above behavior--
1300 ** but it *is* desirable.)
1302 ** The unused offset argument is for the benefit of mktime variants.
1307 localsub(timep
, offset
, tmp
)
1308 const time_t * const timep
;
1310 struct tm
* const tmp
;
1312 register struct state
* sp
;
1313 register const struct ttinfo
* ttisp
;
1315 register struct tm
* result
;
1316 const time_t t
= *timep
;
1321 return gmtsub(timep
, offset
, tmp
);
1322 #endif /* defined ALL_STATE */
1323 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
1324 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
1326 register time_t seconds
;
1327 register time_t tcycles
;
1328 register int_fast64_t icycles
;
1331 seconds
= sp
->ats
[0] - t
;
1332 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
1334 tcycles
= seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
;
1337 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
1339 seconds
= (time_t) icycles
;
1340 seconds
*= YEARSPERREPEAT
;
1341 seconds
*= AVGSECSPERYEAR
;
1344 else newt
-= seconds
;
1345 if (newt
< sp
->ats
[0] ||
1346 newt
> sp
->ats
[sp
->timecnt
- 1])
1347 return NULL
; /* "cannot happen" */
1348 result
= localsub(&newt
, offset
, tmp
);
1349 if (result
== tmp
) {
1350 register time_t newy
;
1352 newy
= tmp
->tm_year
;
1354 newy
-= (time_t)icycles
* YEARSPERREPEAT
;
1355 else newy
+= (time_t)icycles
* YEARSPERREPEAT
;
1356 tmp
->tm_year
= (int)newy
;
1357 if (tmp
->tm_year
!= newy
)
1362 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1364 while (sp
->ttis
[i
].tt_isdst
)
1365 if (++i
>= sp
->typecnt
) {
1370 register int lo
= 1;
1371 register int hi
= sp
->timecnt
;
1374 register int mid
= (lo
+ hi
) / 2;
1376 if (t
< sp
->ats
[mid
])
1380 i
= (int) sp
->types
[lo
- 1];
1382 ttisp
= &sp
->ttis
[i
];
1384 ** To get (wrong) behavior that's compatible with System V Release 2.0
1385 ** you'd replace the statement below with
1386 ** t += ttisp->tt_gmtoff;
1387 ** timesub(&t, 0L, sp, tmp);
1389 result
= timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
1390 tmp
->tm_isdst
= ttisp
->tt_isdst
;
1391 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
1393 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1394 #endif /* defined TM_ZONE */
1400 const time_t * const timep
;
1404 rwlock_wrlock(&lcl_lock
);
1406 result
= localsub(timep
, 0L, &tm
);
1407 rwlock_unlock(&lcl_lock
);
1412 ** Re-entrant version of localtime.
1416 localtime_r(timep
, tmp
)
1417 const time_t * const timep
;
1422 rwlock_rdlock(&lcl_lock
);
1424 result
= localsub(timep
, 0L, tmp
);
1425 rwlock_unlock(&lcl_lock
);
1430 ** gmtsub is to gmtime as localsub is to localtime.
1434 gmtsub(timep
, offset
, tmp
)
1435 const time_t * const timep
;
1437 struct tm
* const tmp
;
1439 register struct tm
* result
;
1441 static mutex_t gmt_mutex
= MUTEX_INITIALIZER
;
1444 mutex_lock(&gmt_mutex
);
1452 gmtptr
= (struct state
*) malloc(sizeof *gmtptr
);
1455 #endif /* defined ALL_STATE */
1458 mutex_unlock(&gmt_mutex
);
1459 result
= timesub(timep
, offset
, gmtptr
, tmp
);
1462 ** Could get fancy here and deliver something such as
1463 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1464 ** but this is no time for a treasure hunt.
1467 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(wildabbr
);
1471 tmp
->TM_ZONE
= (__aconst
char *)__UNCONST(gmt
);
1472 else tmp
->TM_ZONE
= gmtptr
->chars
;
1473 #endif /* defined ALL_STATE */
1475 tmp
->TM_ZONE
= gmtptr
->chars
;
1476 #endif /* State Farm */
1478 #endif /* defined TM_ZONE */
1484 const time_t * const timep
;
1486 return gmtsub(timep
, 0L, &tm
);
1490 ** Re-entrant version of gmtime.
1494 gmtime_r(timep
, tmp
)
1495 const time_t * const timep
;
1498 return gmtsub(timep
, 0L, tmp
);
1504 offtime(timep
, offset
)
1505 const time_t * const timep
;
1508 return gmtsub(timep
, offset
, &tm
);
1511 #endif /* defined STD_INSPIRED */
1514 ** Return the number of leap years through the end of the given year
1515 ** where, to make the math easy, the answer for year zero is defined as zero.
1519 leaps_thru_end_of(y
)
1520 register const int y
;
1522 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
1523 -(leaps_thru_end_of(-(y
+ 1)) + 1);
1527 timesub(timep
, offset
, sp
, tmp
)
1528 const time_t * const timep
;
1530 register const struct state
* const sp
;
1531 register struct tm
* const tmp
;
1533 register const struct lsinfo
* lp
;
1534 register time_t tdays
;
1535 register int idays
; /* unsigned would be so 2003 */
1538 register const int * ip
;
1546 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1547 #endif /* defined ALL_STATE */
1550 #endif /* State Farm */
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
= *timep
/ SECSPERDAY
;
1573 rem
= (long) (*timep
- tdays
* SECSPERDAY
);
1574 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
1576 register time_t tdelta
;
1577 register int idelta
;
1578 register int leapdays
;
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
;
1596 register long seconds
;
1598 seconds
= tdays
* SECSPERDAY
+ 0.5;
1599 tdays
= 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 */
1662 const time_t * const timep
;
1665 ** Section 4.12.3.2 of X3.159-1989 requires that
1666 ** The ctime function converts the calendar time pointed to by timer
1667 ** to local time in the form of a string. It is equivalent to
1668 ** asctime(localtime(timer))
1670 return asctime(localtime(timep
));
1675 const time_t * const timep
;
1680 return asctime_r(localtime_r(timep
, &mytm
), buf
);
1684 ** Adapted from code provided by Robert Elz, who writes:
1685 ** The "best" way to do mktime I think is based on an idea of Bob
1686 ** Kridle's (so its said...) from a long time ago.
1687 ** It does a binary search of the time_t space. Since time_t's are
1688 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1689 ** would still be very reasonable).
1694 #endif /* !defined WRONG */
1697 ** Simplified normalize logic courtesy Paul Eggert.
1701 increment_overflow(number
, delta
)
1709 return (*number
< number0
) != (delta
< 0);
1713 long_increment_overflow(number
, delta
)
1721 return (*number
< number0
) != (delta
< 0);
1725 normalize_overflow(tensptr
, unitsptr
, base
)
1726 int * const tensptr
;
1727 int * const unitsptr
;
1730 register int tensdelta
;
1732 tensdelta
= (*unitsptr
>= 0) ?
1733 (*unitsptr
/ base
) :
1734 (-1 - (-1 - *unitsptr
) / base
);
1735 *unitsptr
-= tensdelta
* base
;
1736 return increment_overflow(tensptr
, tensdelta
);
1740 long_normalize_overflow(tensptr
, unitsptr
, base
)
1741 long * const tensptr
;
1742 int * const unitsptr
;
1745 register int tensdelta
;
1747 tensdelta
= (*unitsptr
>= 0) ?
1748 (*unitsptr
/ base
) :
1749 (-1 - (-1 - *unitsptr
) / base
);
1750 *unitsptr
-= tensdelta
* base
;
1751 return long_increment_overflow(tensptr
, tensdelta
);
1756 register const struct tm
* const atmp
;
1757 register const struct tm
* const btmp
;
1759 register int result
;
1761 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
1762 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
1763 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
1764 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
1765 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
1766 result
= atmp
->tm_sec
- btmp
->tm_sec
;
1771 time2sub(tmp
, funcp
, offset
, okayp
, do_norm_secs
)
1772 struct tm
* const tmp
;
1773 struct tm
* (* const funcp
)(const time_t*, long, struct tm
*);
1776 const int do_norm_secs
;
1778 register const struct state
* sp
;
1781 register int saved_seconds
;
1788 struct tm yourtm
, mytm
;
1793 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
1797 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
1799 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
1802 if (long_normalize_overflow(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
1805 ** Turn y into an actual year number for now.
1806 ** It is converted back to an offset from TM_YEAR_BASE later.
1808 if (long_increment_overflow(&y
, TM_YEAR_BASE
))
1810 while (yourtm
.tm_mday
<= 0) {
1811 if (long_increment_overflow(&y
, -1))
1813 li
= y
+ (1 < yourtm
.tm_mon
);
1814 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
1816 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
1817 li
= y
+ (1 < yourtm
.tm_mon
);
1818 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
1819 if (long_increment_overflow(&y
, 1))
1823 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
1824 if (yourtm
.tm_mday
<= i
)
1826 yourtm
.tm_mday
-= i
;
1827 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
1829 if (long_increment_overflow(&y
, 1))
1833 if (long_increment_overflow(&y
, -TM_YEAR_BASE
))
1836 if (yourtm
.tm_year
!= y
)
1838 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
1840 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
1842 ** We can't set tm_sec to 0, because that might push the
1843 ** time below the minimum representable time.
1844 ** Set tm_sec to 59 instead.
1845 ** This assumes that the minimum representable time is
1846 ** not in the same minute that a leap second was deleted from,
1847 ** which is a safer assumption than using 58 would be.
1849 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
1851 saved_seconds
= yourtm
.tm_sec
;
1852 yourtm
.tm_sec
= SECSPERMIN
- 1;
1854 saved_seconds
= yourtm
.tm_sec
;
1858 ** Do a binary search (this works whatever time_t's type is).
1860 /* LINTED constant */
1861 if (!TYPE_SIGNED(time_t)) {
1864 /* LINTED constant */
1865 } else if (!TYPE_INTEGRAL(time_t)) {
1867 if (sizeof(time_t) > sizeof(float))
1868 /* LINTED assumed double */
1869 hi
= (time_t) DBL_MAX
;
1870 /* LINTED assumed float */
1871 else hi
= (time_t) FLT_MAX
;
1875 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
1880 t
= lo
/ 2 + hi
/ 2;
1885 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
1887 ** Assume that t is too extreme to be represented in
1888 ** a struct tm; arrange things so that it is less
1889 ** extreme on the next pass.
1891 dir
= (t
> 0) ? 1 : -1;
1892 } else dir
= tmcomp(&mytm
, &yourtm
);
1899 } else if (t
== hi
) {
1912 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
1915 ** Right time, wrong type.
1916 ** Hunt for right time, right type.
1917 ** It's okay to guess wrong since the guess
1920 sp
= (const struct state
*)
1921 ((funcp
== localsub
) ? lclptr
: gmtptr
);
1925 #endif /* defined ALL_STATE */
1926 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
1927 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
1929 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
1930 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
1932 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
1933 sp
->ttis
[i
].tt_gmtoff
;
1934 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
1936 if (tmcomp(&mytm
, &yourtm
) != 0)
1938 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
1950 newt
= t
+ saved_seconds
;
1951 if ((newt
< t
) != (saved_seconds
< 0))
1954 if ((*funcp
)(&t
, offset
, tmp
))
1960 time2(tmp
, funcp
, offset
, okayp
)
1961 struct tm
* const tmp
;
1962 struct tm
* (* const funcp
)(const time_t*, long, struct tm
*);
1969 ** First try without normalization of seconds
1970 ** (in case tm_sec contains a value associated with a leap second).
1971 ** If that fails, try with normalization of seconds.
1973 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
);
1974 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
);
1978 time1(tmp
, funcp
, offset
)
1979 struct tm
* const tmp
;
1980 struct tm
* (* const funcp
)(const time_t *, long, struct tm
*);
1984 register const struct state
* sp
;
1985 register int samei
, otheri
;
1986 register int sameind
, otherind
;
1989 int seen
[TZ_MAX_TYPES
];
1990 int types
[TZ_MAX_TYPES
];
1993 if (tmp
->tm_isdst
> 1)
1995 t
= time2(tmp
, funcp
, offset
, &okay
);
1998 ** PCTS code courtesy Grant Sullivan.
2002 if (tmp
->tm_isdst
< 0)
2003 tmp
->tm_isdst
= 0; /* reset to std and try again */
2004 #endif /* defined PCTS */
2006 if (okay
|| tmp
->tm_isdst
< 0)
2008 #endif /* !defined PCTS */
2010 ** We're supposed to assume that somebody took a time of one type
2011 ** and did some math on it that yielded a "struct tm" that's bad.
2012 ** We try to divine the type they started from and adjust to the
2015 sp
= (const struct state
*) ((funcp
== localsub
) ? lclptr
: gmtptr
);
2019 #endif /* defined ALL_STATE */
2020 for (i
= 0; i
< sp
->typecnt
; ++i
)
2023 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
2024 if (!seen
[sp
->types
[i
]]) {
2025 seen
[sp
->types
[i
]] = TRUE
;
2026 types
[nseen
++] = sp
->types
[i
];
2028 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2029 samei
= types
[sameind
];
2030 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2032 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2033 otheri
= types
[otherind
];
2034 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
2036 tmp
->tm_sec
+= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2037 sp
->ttis
[samei
].tt_gmtoff
);
2038 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2039 t
= time2(tmp
, funcp
, offset
, &okay
);
2042 tmp
->tm_sec
-= (int)(sp
->ttis
[otheri
].tt_gmtoff
-
2043 sp
->ttis
[samei
].tt_gmtoff
);
2044 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2052 struct tm
* const tmp
;
2056 rwlock_wrlock(&lcl_lock
);
2058 result
= time1(tmp
, localsub
, 0L);
2059 rwlock_unlock(&lcl_lock
);
2067 struct tm
* const tmp
;
2069 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2075 struct tm
* const tmp
;
2078 return time1(tmp
, gmtsub
, 0L);
2082 timeoff(tmp
, offset
)
2083 struct tm
* const tmp
;
2087 return time1(tmp
, gmtsub
, offset
);
2090 #endif /* defined STD_INSPIRED */
2095 ** The following is supplied for compatibility with
2096 ** previous versions of the CMUCS runtime library.
2101 struct tm
* const tmp
;
2103 const time_t t
= mktime(tmp
);
2110 #endif /* defined CMUCS */
2113 ** XXX--is the below the right way to conditionalize??
2119 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2120 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2121 ** is not the case if we are accounting for leap seconds.
2122 ** So, we provide the following conversion routines for use
2123 ** when exchanging timestamps with POSIX conforming systems.
2130 register struct state
* sp
;
2131 register struct lsinfo
* lp
;
2138 if (*timep
>= lp
->ls_trans
)
2150 rwlock_wrlock(&lcl_lock
);
2152 result
= t
- leapcorr(&t
);
2153 rwlock_unlock(&lcl_lock
);
2164 rwlock_wrlock(&lcl_lock
);
2167 ** For a positive leap second hit, the result
2168 ** is not unique. For a negative leap second
2169 ** hit, the corresponding time doesn't exist,
2170 ** so we return an adjacent second.
2172 x
= t
+ leapcorr(&t
);
2173 y
= x
- leapcorr(&x
);
2177 y
= x
- leapcorr(&x
);
2180 rwlock_unlock(&lcl_lock
);
2186 y
= x
- leapcorr(&x
);
2189 rwlock_unlock(&lcl_lock
);
2193 rwlock_unlock(&lcl_lock
);
2197 #endif /* defined STD_INSPIRED */