2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
8 static char elsieid
[] = "@(#)localtime.c 8.5";
9 #endif /* !defined NOID */
10 #endif /* !defined lint */
13 ** Leap second handling from Bradley White.
14 ** POSIX-style TZ environment variable handling from Guy Harris.
22 #include "float.h" /* for FLT_MAX and DBL_MAX */
24 #ifndef TZ_ABBR_MAX_LEN
25 #define TZ_ABBR_MAX_LEN 16
26 #endif /* !defined TZ_ABBR_MAX_LEN */
28 #ifndef TZ_ABBR_CHAR_SET
29 #define TZ_ABBR_CHAR_SET \
30 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
31 #endif /* !defined TZ_ABBR_CHAR_SET */
33 #ifndef TZ_ABBR_ERR_CHAR
34 #define TZ_ABBR_ERR_CHAR '_'
35 #endif /* !defined TZ_ABBR_ERR_CHAR */
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";
76 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
77 ** We default to US rules as of 1999-08-17.
78 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
79 ** implementation dependent; for historical reasons, US rules are a
82 #ifndef TZDEFRULESTRING
83 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
84 #endif /* !defined TZDEFDST */
86 struct ttinfo
{ /* time type information */
87 long tt_gmtoff
; /* UTC offset in seconds */
88 int tt_isdst
; /* used to set tm_isdst */
89 int tt_abbrind
; /* abbreviation list index */
90 int tt_ttisstd
; /* TRUE if transition is std time */
91 int tt_ttisgmt
; /* TRUE if transition is UTC */
94 struct lsinfo
{ /* leap second information */
95 time_t ls_trans
; /* transition time */
96 long ls_corr
; /* correction to apply */
99 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
102 #define MY_TZNAME_MAX TZNAME_MAX
103 #endif /* defined TZNAME_MAX */
105 #define MY_TZNAME_MAX 255
106 #endif /* !defined TZNAME_MAX */
115 time_t ats
[TZ_MAX_TIMES
];
116 unsigned char types
[TZ_MAX_TIMES
];
117 struct ttinfo ttis
[TZ_MAX_TYPES
];
118 char chars
[BIGGEST(BIGGEST(TZ_MAX_CHARS
+ 1, sizeof gmt
),
119 (2 * (MY_TZNAME_MAX
+ 1)))];
120 struct lsinfo lsis
[TZ_MAX_LEAPS
];
124 int r_type
; /* type of rule--see below */
125 int r_day
; /* day number of rule */
126 int r_week
; /* week number of rule */
127 int r_mon
; /* month number of rule */
128 long r_time
; /* transition time of rule */
131 #define JULIAN_DAY 0 /* Jn - Julian day */
132 #define DAY_OF_YEAR 1 /* n - day of year */
133 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
136 ** Prototypes for static functions.
139 static struct tm
* gmtsub
P((const time_t * timep
, long offset
,
141 static struct tm
* localsub
P((const time_t * timep
, long offset
,
143 static int increment_overflow
P((int * number
, int delta
));
144 static int leaps_thru_end_of
P((int y
));
145 static int long_increment_overflow
P((long * number
, int delta
));
146 static int long_normalize_overflow
P((long * tensptr
,
147 int * unitsptr
, int base
));
148 static int normalize_overflow
P((int * tensptr
, int * unitsptr
,
150 static time_t time1
P((struct tm
* tmp
,
151 struct tm
* (*funcp
) P((const time_t *,
154 static time_t time2
P((struct tm
*tmp
,
155 struct tm
* (*funcp
) P((const time_t *,
157 long offset
, int * okayp
));
158 static time_t time2sub
P((struct tm
*tmp
,
159 struct tm
* (*funcp
) P((const time_t *,
161 long offset
, int * okayp
, int do_norm_secs
));
162 static struct tm
* timesub
P((const time_t * timep
, long offset
,
163 const struct state
* sp
, struct tm
* tmp
));
164 static int tmcomp
P((const struct tm
* atmp
,
165 const struct tm
* btmp
));
170 struct tm
* __gmtime_r_fallback(const time_t* timep
, struct tm
* tmp
);
171 time_t __mktime_fallback(struct tm
* tmp
);
172 time_t timegm(struct tm
* const tmp
);
174 static struct state lclmem
;
175 static struct state gmtmem
;
176 #define lclptr (&lclmem)
177 #define gmtptr (&gmtmem)
179 static int gmt_is_set
;
181 static const int mon_lengths
[2][MONSPERYEAR
] = {
182 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
183 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
186 static const int year_lengths
[2] = {
187 DAYSPERNYEAR
, DAYSPERLYEAR
191 ** The easy way to behave "as if no library function calls" localtime
192 ** is to not call it--so we drop its guts into "localsub", which can be
193 ** freely called. (And no, the PANS doesn't require the above behavior--
194 ** but it *is* desirable.)
196 ** The unused offset argument is for the benefit of mktime variants.
201 localsub(timep
, offset
, tmp
)
202 const time_t * const timep
;
204 struct tm
* const tmp
;
206 register struct state
* sp
;
207 register const struct ttinfo
* ttisp
;
209 register struct tm
* result
;
210 const time_t t
= *timep
;
213 if ((sp
->goback
&& t
< sp
->ats
[0]) ||
214 (sp
->goahead
&& t
> sp
->ats
[sp
->timecnt
- 1])) {
216 register time_t seconds
;
217 register time_t tcycles
;
218 register int_fast64_t icycles
;
221 seconds
= sp
->ats
[0] - t
;
222 else seconds
= t
- sp
->ats
[sp
->timecnt
- 1];
224 tcycles
= seconds
/ YEARSPERREPEAT
/ AVGSECSPERYEAR
;
227 if (tcycles
- icycles
>= 1 || icycles
- tcycles
>= 1)
230 seconds
*= YEARSPERREPEAT
;
231 seconds
*= AVGSECSPERYEAR
;
234 else newt
-= seconds
;
235 if (newt
< sp
->ats
[0] ||
236 newt
> sp
->ats
[sp
->timecnt
- 1])
237 return NULL
; /* "cannot happen" */
238 result
= localsub(&newt
, offset
, tmp
);
240 register time_t newy
;
244 newy
-= icycles
* YEARSPERREPEAT
;
245 else newy
+= icycles
* YEARSPERREPEAT
;
247 if (tmp
->tm_year
!= newy
)
252 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
254 while (sp
->ttis
[i
].tt_isdst
)
255 if (++i
>= sp
->typecnt
) {
261 register int hi
= sp
->timecnt
;
264 register int mid
= (lo
+ hi
) >> 1;
266 if (t
< sp
->ats
[mid
])
270 i
= (int) sp
->types
[lo
- 1];
272 ttisp
= &sp
->ttis
[i
];
274 ** To get (wrong) behavior that's compatible with System V Release 2.0
275 ** you'd replace the statement below with
276 ** t += ttisp->tt_gmtoff;
277 ** timesub(&t, 0L, sp, tmp);
279 result
= timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
);
280 tmp
->tm_isdst
= ttisp
->tt_isdst
;
281 tzname
[tmp
->tm_isdst
] = &sp
->chars
[ttisp
->tt_abbrind
];
283 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
284 #endif /* defined TM_ZONE */
290 ** gmtsub is to gmtime as localsub is to localtime.
294 gmtsub(timep
, offset
, tmp
)
295 const time_t * const timep
;
297 struct tm
* const tmp
;
299 register struct tm
* result
;
303 result
= timesub(timep
, offset
, gmtptr
, tmp
);
306 ** Could get fancy here and deliver something such as
307 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
308 ** but this is no time for a treasure hunt.
311 tmp
->TM_ZONE
= wildabbr
;
313 tmp
->TM_ZONE
= gmtptr
->chars
;
314 #endif /* defined TM_ZONE */
320 // used in Haiku as fallback when the locale backend could not be loaded
322 __gmtime_r_fallback(const time_t* timep
, struct tm
* tmp
)
324 return gmtsub(timep
, 0L, tmp
);
328 ** Return the number of leap years through the end of the given year
329 ** where, to make the math easy, the answer for year zero is defined as zero.
334 register const int y
;
336 return (y
>= 0) ? (y
/ 4 - y
/ 100 + y
/ 400) :
337 -(leaps_thru_end_of(-(y
+ 1)) + 1);
341 timesub(timep
, offset
, sp
, tmp
)
342 const time_t * const timep
;
344 register const struct state
* const sp
;
345 register struct tm
* const tmp
;
347 register const struct lsinfo
* lp
;
348 register time_t tdays
;
349 register int idays
; /* unsigned would be so 2003 */
352 register const int * ip
;
362 if (*timep
>= lp
->ls_trans
) {
363 if (*timep
== lp
->ls_trans
) {
364 hit
= ((i
== 0 && lp
->ls_corr
> 0) ||
365 lp
->ls_corr
> sp
->lsis
[i
- 1].ls_corr
);
368 sp
->lsis
[i
].ls_trans
==
369 sp
->lsis
[i
- 1].ls_trans
+ 1 &&
370 sp
->lsis
[i
].ls_corr
==
371 sp
->lsis
[i
- 1].ls_corr
+ 1) {
381 tdays
= *timep
/ SECSPERDAY
;
382 rem
= *timep
- tdays
* SECSPERDAY
;
383 while (tdays
< 0 || tdays
>= year_lengths
[isleap(y
)]) {
385 register time_t tdelta
;
387 register int leapdays
;
389 tdelta
= tdays
/ DAYSPERLYEAR
;
391 if (tdelta
- idelta
>= 1 || idelta
- tdelta
>= 1)
394 idelta
= (tdays
< 0) ? -1 : 1;
396 if (increment_overflow(&newy
, idelta
))
398 leapdays
= leaps_thru_end_of(newy
- 1) -
399 leaps_thru_end_of(y
- 1);
400 tdays
-= ((time_t) newy
- y
) * DAYSPERNYEAR
;
405 register long seconds
;
407 seconds
= tdays
* SECSPERDAY
+ 0.5;
408 tdays
= seconds
/ SECSPERDAY
;
409 rem
+= seconds
- tdays
* SECSPERDAY
;
412 ** Given the range, we can now fearlessly cast...
415 rem
+= offset
- corr
;
420 while (rem
>= SECSPERDAY
) {
425 if (increment_overflow(&y
, -1))
427 idays
+= year_lengths
[isleap(y
)];
429 while (idays
>= year_lengths
[isleap(y
)]) {
430 idays
-= year_lengths
[isleap(y
)];
431 if (increment_overflow(&y
, 1))
435 if (increment_overflow(&tmp
->tm_year
, -TM_YEAR_BASE
))
437 tmp
->tm_yday
= idays
;
439 ** The "extra" mods below avoid overflow problems.
441 tmp
->tm_wday
= EPOCH_WDAY
+
442 ((y
- EPOCH_YEAR
) % DAYSPERWEEK
) *
443 (DAYSPERNYEAR
% DAYSPERWEEK
) +
444 leaps_thru_end_of(y
- 1) -
445 leaps_thru_end_of(EPOCH_YEAR
- 1) +
447 tmp
->tm_wday
%= DAYSPERWEEK
;
448 if (tmp
->tm_wday
< 0)
449 tmp
->tm_wday
+= DAYSPERWEEK
;
450 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
452 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
454 ** A positive leap second requires a special
455 ** representation. This uses "... ??:59:60" et seq.
457 tmp
->tm_sec
= (int) (rem
% SECSPERMIN
) + hit
;
458 ip
= mon_lengths
[isleap(y
)];
459 for (tmp
->tm_mon
= 0; idays
>= ip
[tmp
->tm_mon
]; ++(tmp
->tm_mon
))
460 idays
-= ip
[tmp
->tm_mon
];
461 tmp
->tm_mday
= (int) (idays
+ 1);
464 tmp
->TM_GMTOFF
= offset
;
465 #endif /* defined TM_GMTOFF */
470 ** Adapted from code provided by Robert Elz, who writes:
471 ** The "best" way to do mktime I think is based on an idea of Bob
472 ** Kridle's (so its said...) from a long time ago.
473 ** It does a binary search of the time_t space. Since time_t's are
474 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
475 ** would still be very reasonable).
480 #endif /* !defined WRONG */
483 ** Simplified normalize logic courtesy Paul Eggert.
487 increment_overflow(number
, delta
)
495 return (*number
< number0
) != (delta
< 0);
499 long_increment_overflow(number
, delta
)
507 return (*number
< number0
) != (delta
< 0);
511 normalize_overflow(tensptr
, unitsptr
, base
)
513 int * const unitsptr
;
516 register int tensdelta
;
518 tensdelta
= (*unitsptr
>= 0) ?
520 (-1 - (-1 - *unitsptr
) / base
);
521 *unitsptr
-= tensdelta
* base
;
522 return increment_overflow(tensptr
, tensdelta
);
526 long_normalize_overflow(tensptr
, unitsptr
, base
)
527 long * const tensptr
;
528 int * const unitsptr
;
531 register int tensdelta
;
533 tensdelta
= (*unitsptr
>= 0) ?
535 (-1 - (-1 - *unitsptr
) / base
);
536 *unitsptr
-= tensdelta
* base
;
537 return long_increment_overflow(tensptr
, tensdelta
);
542 register const struct tm
* const atmp
;
543 register const struct tm
* const btmp
;
547 if ((result
= (atmp
->tm_year
- btmp
->tm_year
)) == 0 &&
548 (result
= (atmp
->tm_mon
- btmp
->tm_mon
)) == 0 &&
549 (result
= (atmp
->tm_mday
- btmp
->tm_mday
)) == 0 &&
550 (result
= (atmp
->tm_hour
- btmp
->tm_hour
)) == 0 &&
551 (result
= (atmp
->tm_min
- btmp
->tm_min
)) == 0)
552 result
= atmp
->tm_sec
- btmp
->tm_sec
;
557 time2sub(tmp
, funcp
, offset
, okayp
, do_norm_secs
)
558 struct tm
* const tmp
;
559 struct tm
* (* const funcp
) P((const time_t*, long, struct tm
*));
562 const int do_norm_secs
;
564 register const struct state
* sp
;
567 register int saved_seconds
;
574 struct tm yourtm
, mytm
;
579 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
583 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
585 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
588 if (long_normalize_overflow(&y
, &yourtm
.tm_mon
, MONSPERYEAR
))
591 ** Turn y into an actual year number for now.
592 ** It is converted back to an offset from TM_YEAR_BASE later.
594 if (long_increment_overflow(&y
, TM_YEAR_BASE
))
596 while (yourtm
.tm_mday
<= 0) {
597 if (long_increment_overflow(&y
, -1))
599 li
= y
+ (1 < yourtm
.tm_mon
);
600 yourtm
.tm_mday
+= year_lengths
[isleap(li
)];
602 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
603 li
= y
+ (1 < yourtm
.tm_mon
);
604 yourtm
.tm_mday
-= year_lengths
[isleap(li
)];
605 if (long_increment_overflow(&y
, 1))
609 i
= mon_lengths
[isleap(y
)][yourtm
.tm_mon
];
610 if (yourtm
.tm_mday
<= i
)
613 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
615 if (long_increment_overflow(&y
, 1))
619 if (long_increment_overflow(&y
, -TM_YEAR_BASE
))
622 if (yourtm
.tm_year
!= y
)
624 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
626 else if (y
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
628 ** We can't set tm_sec to 0, because that might push the
629 ** time below the minimum representable time.
630 ** Set tm_sec to 59 instead.
631 ** This assumes that the minimum representable time is
632 ** not in the same minute that a leap second was deleted from,
633 ** which is a safer assumption than using 58 would be.
635 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
637 saved_seconds
= yourtm
.tm_sec
;
638 yourtm
.tm_sec
= SECSPERMIN
- 1;
640 saved_seconds
= yourtm
.tm_sec
;
644 ** Do a binary search (this works whatever time_t's type is).
646 if (!TYPE_SIGNED(time_t)) {
649 } else if (!TYPE_INTEGRAL(time_t)) {
650 if (sizeof(time_t) > sizeof(float))
651 hi
= (time_t) DBL_MAX
;
652 else hi
= (time_t) FLT_MAX
;
656 for (i
= 0; i
< (int) TYPE_BIT(time_t) - 1; ++i
)
666 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
668 ** Assume that t is too extreme to be represented in
669 ** a struct tm; arrange things so that it is less
670 ** extreme on the next pass.
672 dir
= (t
> 0) ? 1 : -1;
673 } else dir
= tmcomp(&mytm
, &yourtm
);
680 } else if (t
== hi
) {
693 if (yourtm
.tm_isdst
< 0 || mytm
.tm_isdst
== yourtm
.tm_isdst
)
696 ** Right time, wrong type.
697 ** Hunt for right time, right type.
698 ** It's okay to guess wrong since the guess
702 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
704 sp
= (const struct state
*)
705 (((void *) funcp
== (void *) localsub
) ?
707 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
708 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
710 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
711 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
713 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
714 sp
->ttis
[i
].tt_gmtoff
;
715 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
717 if (tmcomp(&mytm
, &yourtm
) != 0)
719 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
731 newt
= t
+ saved_seconds
;
732 if ((newt
< t
) != (saved_seconds
< 0))
735 if ((*funcp
)(&t
, offset
, tmp
))
741 time2(tmp
, funcp
, offset
, okayp
)
742 struct tm
* const tmp
;
743 struct tm
* (* const funcp
) P((const time_t*, long, struct tm
*));
750 ** First try without normalization of seconds
751 ** (in case tm_sec contains a value associated with a leap second).
752 ** If that fails, try with normalization of seconds.
754 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
);
755 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
);
759 time1(tmp
, funcp
, offset
)
760 struct tm
* const tmp
;
761 struct tm
* (* const funcp
) P((const time_t *, long, struct tm
*));
765 register const struct state
* sp
;
766 register int samei
, otheri
;
767 register int sameind
, otherind
;
770 int seen
[TZ_MAX_TYPES
];
771 int types
[TZ_MAX_TYPES
];
774 if (tmp
->tm_isdst
> 1)
776 t
= time2(tmp
, funcp
, offset
, &okay
);
778 ** PCTS code courtesy Grant Sullivan.
782 if (tmp
->tm_isdst
< 0)
783 tmp
->tm_isdst
= 0; /* reset to std and try again */
785 ** We're supposed to assume that somebody took a time of one type
786 ** and did some math on it that yielded a "struct tm" that's bad.
787 ** We try to divine the type they started from and adjust to the
791 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
793 sp
= (const struct state
*) (((void *) funcp
== (void *) localsub
) ?
795 for (i
= 0; i
< sp
->typecnt
; ++i
)
798 for (i
= sp
->timecnt
- 1; i
>= 0; --i
)
799 if (!seen
[sp
->types
[i
]]) {
800 seen
[sp
->types
[i
]] = TRUE
;
801 types
[nseen
++] = sp
->types
[i
];
803 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
804 samei
= types
[sameind
];
805 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
807 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
808 otheri
= types
[otherind
];
809 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
811 tmp
->tm_sec
+= sp
->ttis
[otheri
].tt_gmtoff
-
812 sp
->ttis
[samei
].tt_gmtoff
;
813 tmp
->tm_isdst
= !tmp
->tm_isdst
;
814 t
= time2(tmp
, funcp
, offset
, &okay
);
817 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
818 sp
->ttis
[samei
].tt_gmtoff
;
819 tmp
->tm_isdst
= !tmp
->tm_isdst
;
826 // used in Haiku as fallback when the locale backend could not be loaded
828 __mktime_fallback(struct tm
* tmp
)
830 return time1(tmp
, localsub
, 0L);
837 struct tm
* const tmp
;
840 return time1(tmp
, gmtsub
, 0L);