1 /* Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Paul Eggert (eggert@twinsun.com).
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 /* Define this to have a standalone program to test this implementation of
28 /* Some systems require that one of these symbols be defined in
29 order to declare localtime_r properly. */
30 #ifndef __EXTENSIONS__
31 # define __EXTENSIONS__ 1
33 #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
34 # define _POSIX_THREAD_SAFE_FUNCTIONS 1
38 # define HAVE_LIMITS_H 1
39 # define HAVE_LOCALTIME_R 1
40 # define STDC_HEADERS 1
43 /* Assume that leap seconds are possible, unless told otherwise.
44 If the host has a `zic' command with a `-L leapsecondfilename' option,
45 then it supports leap seconds; otherwise it probably doesn't. */
46 #ifndef LEAP_SECONDS_POSSIBLE
47 # define LEAP_SECONDS_POSSIBLE 1
50 /* Some systems require <unistd.h> to be included before <time.h>
51 for localtime_r to be declared properly. */
56 #include <sys/types.h> /* Some systems define `time_t' here. */
68 /* Make it work even if the system's libc has its own mktime routine. */
69 # define mktime my_mktime
73 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
74 # define __P(args) args
84 /* The extra casts work around common compiler bugs. */
85 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
86 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
87 It is necessary at least when t == time_t. */
88 #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
89 ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
90 #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
93 # define INT_MIN TYPE_MINIMUM (int)
96 # define INT_MAX TYPE_MAXIMUM (int)
100 # define TIME_T_MIN TYPE_MINIMUM (time_t)
103 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
106 #define TM_YEAR_BASE 1900
107 #define EPOCH_YEAR 1970
110 /* Nonzero if YEAR is a leap year (every 4 years,
111 except every 100th isn't, and every 400th is). */
112 # define __isleap(year) \
113 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
116 /* How many days come before each month (0-12). */
117 const unsigned short int __mon_yday
[2][13] =
120 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
122 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
125 static struct tm
*ranged_convert
__P ((struct tm
*(*) __P ((const time_t *,
127 time_t *, struct tm
*));
128 static time_t ydhms_tm_diff
__P ((int, int, int, int, int, const struct tm
*));
129 time_t __mktime_internal
__P ((struct tm
*,
130 struct tm
*(*) (const time_t *, struct tm
*),
135 # define localtime_r __localtime_r
137 # if HAVE_LOCALTIME_R == defined localtime_r
138 /* Provide our own substitute for a missing or possibly broken localtime_r. */
139 static struct tm
*my_mktime_localtime_r
__P ((const time_t *, struct tm
*));
141 my_mktime_localtime_r (t
, tp
)
146 /* Digital Unix 4.0A and 4.0D have a macro localtime_r with the
147 standard meaning, along with an unwanted, nonstandard function
148 localtime_r. The placeholder function my_mktime_localtime_r
149 invokes the macro; use that instead of the system's bogus
151 return localtime_r (t
, tp
);
153 # else /* ! defined (localtime_r) */
154 /* Approximate localtime_r as best we can in its absence. */
155 struct tm
*l
= localtime (t
);
160 # endif /* ! defined localtime_r */
162 # define localtime_r my_mktime_localtime_r
163 # endif /* HAVE_LOCALTIME_R == defined localtime_r */
167 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
168 measured in seconds, ignoring leap seconds.
169 YEAR uses the same numbering as TM->tm_year.
170 All values are in range, except possibly YEAR.
171 If TP is null, return a nonzero value.
172 If overflow occurs, yield the low order bits of the correct answer. */
174 ydhms_tm_diff (year
, yday
, hour
, min
, sec
, tp
)
175 int year
, yday
, hour
, min
, sec
;
182 /* Compute intervening leap days correctly even if year is negative.
183 Take care to avoid int overflow. time_t overflow is OK, since
184 only the low order bits of the correct time_t answer are needed.
185 Don't convert to time_t until after all divisions are done, since
186 time_t might be unsigned. */
187 int a4
= (year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (year
& 3);
188 int b4
= (tp
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (tp
->tm_year
& 3);
189 int a100
= a4
/ 25 - (a4
% 25 < 0);
190 int b100
= b4
/ 25 - (b4
% 25 < 0);
191 int a400
= a100
>> 2;
192 int b400
= b100
>> 2;
193 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
194 time_t years
= year
- (time_t) tp
->tm_year
;
195 time_t days
= (365 * years
+ intervening_leap_days
196 + (yday
- tp
->tm_yday
));
197 return (60 * (60 * (24 * days
+ (hour
- tp
->tm_hour
))
198 + (min
- tp
->tm_min
))
199 + (sec
- tp
->tm_sec
));
204 static time_t localtime_offset
;
206 /* Convert *TP to a time_t value. */
212 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
213 time zone names contained in the external variable `tzname' shall
214 be set as if the tzset() function had been called. */
218 return __mktime_internal (tp
, localtime_r
, &localtime_offset
);
221 /* Use CONVERT to convert *T to a broken down time in *TP.
222 If *T is out of range for conversion, adjust it so that
223 it is the nearest in-range value and then convert that. */
225 ranged_convert (convert
, t
, tp
)
226 struct tm
*(*convert
) __P ((const time_t *, struct tm
*));
232 if (! (r
= (*convert
) (t
, tp
)) && *t
)
238 /* BAD is a known unconvertible time_t, and OK is a known good one.
239 Use binary search to narrow the range between BAD and OK until
241 while (bad
!= ok
+ (bad
< 0 ? -1 : 1))
243 time_t mid
= *t
= (bad
< 0
244 ? bad
+ ((ok
- bad
) >> 1)
245 : ok
+ ((bad
- ok
) >> 1));
246 if ((r
= (*convert
) (t
, tp
)))
257 /* The last conversion attempt failed;
258 revert to the most recent successful attempt. */
269 /* Convert *TP to a time_t value, inverting
270 the monotonic and mostly-unit-linear conversion function CONVERT.
271 Use *OFFSET to keep track of a guess at the offset of the result,
272 compared to what the result would be for UTC without leap seconds.
273 If *OFFSET's guess is correct, only one CONVERT call is needed. */
275 __mktime_internal (tp
, convert
, offset
)
277 struct tm
*(*convert
) __P ((const time_t *, struct tm
*));
280 time_t t
, dt
, t0
, t1
, t2
;
283 /* The maximum number of probes (calls to CONVERT) should be enough
284 to handle any combinations of time zone rule changes, solar time,
285 leap seconds, and oscillations around a spring-forward gap.
286 POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
287 int remaining_probes
= 6;
289 /* Time requested. Copy it in case CONVERT modifies *TP; this can
290 occur if TP is localtime's returned value and CONVERT is localtime. */
291 int sec
= tp
->tm_sec
;
292 int min
= tp
->tm_min
;
293 int hour
= tp
->tm_hour
;
294 int mday
= tp
->tm_mday
;
295 int mon
= tp
->tm_mon
;
296 int year_requested
= tp
->tm_year
;
297 int isdst
= tp
->tm_isdst
;
299 /* Ensure that mon is in range, and set year accordingly. */
300 int mon_remainder
= mon
% 12;
301 int negative_mon_remainder
= mon_remainder
< 0;
302 int mon_years
= mon
/ 12 - negative_mon_remainder
;
303 int year
= year_requested
+ mon_years
;
305 /* The other values need not be in range:
306 the remaining code handles minor overflows correctly,
307 assuming int and time_t arithmetic wraps around.
308 Major overflows are caught at the end. */
310 /* Calculate day of year from year, month, and day of month.
311 The result need not be in range. */
312 int yday
= ((__mon_yday
[__isleap (year
+ TM_YEAR_BASE
)]
313 [mon_remainder
+ 12 * negative_mon_remainder
])
316 int sec_requested
= sec
;
317 #if LEAP_SECONDS_POSSIBLE
318 /* Handle out-of-range seconds specially,
319 since ydhms_tm_diff assumes every minute has 60 seconds. */
326 /* Invert CONVERT by probing. First assume the same offset as last time.
327 Then repeatedly use the error to improve the guess. */
329 tm
.tm_year
= EPOCH_YEAR
- TM_YEAR_BASE
;
330 tm
.tm_yday
= tm
.tm_hour
= tm
.tm_min
= tm
.tm_sec
= 0;
331 t0
= ydhms_tm_diff (year
, yday
, hour
, min
, sec
, &tm
);
333 for (t
= t1
= t2
= t0
+ *offset
;
334 (dt
= ydhms_tm_diff (year
, yday
, hour
, min
, sec
,
335 ranged_convert (convert
, &t
, &tm
)));
336 t1
= t2
, t2
= t
, t
+= dt
)
337 if (t
== t1
&& t
!= t2
338 && (isdst
< 0 || tm
.tm_isdst
< 0
339 || (isdst
!= 0) != (tm
.tm_isdst
!= 0)))
340 /* We can't possibly find a match, as we are oscillating
341 between two values. The requested time probably falls
342 within a spring-forward gap of size DT. Follow the common
343 practice in this case, which is to return a time that is DT
344 away from the requested time, preferring a time whose
345 tm_isdst differs from the requested value. In practice,
346 this is more useful than returning -1. */
348 else if (--remaining_probes
== 0)
351 /* If we have a match, check whether tm.tm_isdst has the requested
353 if (dt
== 0 && isdst
>= 0 && isdst
!= tm
.tm_isdst
)
355 int dst_diff
= (isdst
!= 0) - (tm
.tm_isdst
!= 0);
358 /* Move three hours in the direction indicated by the disagreement,
359 probe some more, and switch to a new time if found.
360 The largest known fallback due to daylight savings is two hours:
361 once, in Newfoundland, 1988-10-30 02:00 -> 00:00.
362 But some programs (e.g. testsuites) probe for larger differences
363 between DST and normal time so switch by three hours. No
364 normal program does this so we do not account for more than
365 three hours difference. */
366 time_t ot
= t
- 3 * 60 * 60 * dst_diff
;
372 while (--remaining_probes
!= 0)
374 if (! (dt
= ydhms_tm_diff (year
, yday
, hour
, min
, sec
,
375 ranged_convert (convert
, &ot
,
377 || tmptm
.tm_isdst
!= isdst
)
383 break; /* Avoid a redundant probe. */
386 if (otm
.tm_isdst
!= -1)
396 #if LEAP_SECONDS_POSSIBLE
397 if (sec_requested
!= tm
.tm_sec
)
399 /* Adjust time to reflect the tm_sec requested, not the normalized value.
400 Also, repair any damage from a false match due to a leap second. */
401 t
+= sec_requested
- sec
+ (sec
== 0 && tm
.tm_sec
== 60);
402 if (! (*convert
) (&t
, &tm
))
407 if (TIME_T_MAX
/ INT_MAX
/ 366 / 24 / 60 / 60 < 3)
409 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
410 so check for major overflows. A gross check suffices,
411 since if t has overflowed, it is off by a multiple of
412 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
413 the difference that is bounded by a small value. */
415 double dyear
= (double) year_requested
+ mon_years
- tm
.tm_year
;
416 double dday
= 366 * dyear
+ mday
;
417 double dsec
= 60 * (60 * (24 * dday
+ hour
) + min
) + sec_requested
;
419 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
420 correct results, ie., it erroneously gives a positive value
421 of 715827882. Setting a variable first then doing math on it
422 seems to work. (ghazi@caip.rutgers.edu) */
424 const time_t time_t_max
= TIME_T_MAX
;
425 const time_t time_t_min
= TIME_T_MIN
;
427 if (time_t_max
/ 3 - time_t_min
/ 3 < (dsec
< 0 ? - dsec
: dsec
))
436 weak_alias (mktime
, timelocal
)
446 return ((a
->tm_sec
^ b
->tm_sec
)
447 | (a
->tm_min
^ b
->tm_min
)
448 | (a
->tm_hour
^ b
->tm_hour
)
449 | (a
->tm_mday
^ b
->tm_mday
)
450 | (a
->tm_mon
^ b
->tm_mon
)
451 | (a
->tm_year
^ b
->tm_year
)
452 | (a
->tm_mday
^ b
->tm_mday
)
453 | (a
->tm_yday
^ b
->tm_yday
)
454 | (a
->tm_isdst
^ b
->tm_isdst
));
462 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
463 tp
->tm_year
+ TM_YEAR_BASE
, tp
->tm_mon
+ 1, tp
->tm_mday
,
464 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
,
465 tp
->tm_yday
, tp
->tm_wday
, tp
->tm_isdst
);
471 check_result (tk
, tmk
, tl
, lt
)
477 if (tk
!= tl
|| !lt
|| not_equal_tm (&tmk
, lt
))
481 printf (")\nyields (");
483 printf (") == %ld, should be %ld\n", (long) tl
, (long) tk
);
496 struct tm tm
, tmk
, tml
;
501 if ((argc
== 3 || argc
== 4)
502 && (sscanf (argv
[1], "%d-%d-%d%c",
503 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
, &trailer
)
505 && (sscanf (argv
[2], "%d:%d:%d%c",
506 &tm
.tm_hour
, &tm
.tm_min
, &tm
.tm_sec
, &trailer
)
509 tm
.tm_year
-= TM_YEAR_BASE
;
511 tm
.tm_isdst
= argc
== 3 ? -1 : atoi (argv
[3]);
514 lt
= localtime (&tl
);
520 printf ("mktime returns %ld == ", (long) tl
);
523 status
= check_result (tl
, tmk
, tl
, lt
);
525 else if (argc
== 4 || (argc
== 5 && strcmp (argv
[4], "-") == 0))
527 time_t from
= atol (argv
[1]);
528 time_t by
= atol (argv
[2]);
529 time_t to
= atol (argv
[3]);
532 for (tl
= from
; tl
<= to
; tl
+= by
)
534 lt
= localtime (&tl
);
539 status
|= check_result (tk
, tmk
, tl
, tml
);
543 printf ("localtime (%ld) yields 0\n", (long) tl
);
548 for (tl
= from
; tl
<= to
; tl
+= by
)
550 /* Null benchmark. */
551 lt
= localtime (&tl
);
556 status
|= check_result (tk
, tmk
, tl
, tml
);
560 printf ("localtime (%ld) yields 0\n", (long) tl
);
567 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
568 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
569 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
570 argv
[0], argv
[0], argv
[0]);
579 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"