Update.
[glibc.git] / time / mktime.c
blob6135d70bd67a5a008fc72862cc1b8f2de6d91d0b
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
21 mktime. */
22 /* #define DEBUG 1 */
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
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
32 #endif
33 #ifndef _POSIX_THREAD_SAFE_FUNCTIONS
34 # define _POSIX_THREAD_SAFE_FUNCTIONS 1
35 #endif
37 #ifdef _LIBC
38 # define HAVE_LIMITS_H 1
39 # define HAVE_LOCALTIME_R 1
40 # define STDC_HEADERS 1
41 #endif
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
48 #endif
50 /* Some systems require <unistd.h> to be included before <time.h>
51 for localtime_r to be declared properly. */
52 #if HAVE_UNISTD_H
53 # include <unistd.h>
54 #endif
56 #include <sys/types.h> /* Some systems define `time_t' here. */
57 #include <time.h>
59 #if HAVE_LIMITS_H
60 # include <limits.h>
61 #endif
63 #if DEBUG
64 # include <stdio.h>
65 # if STDC_HEADERS
66 # include <stdlib.h>
67 # endif
68 /* Make it work even if the system's libc has its own mktime routine. */
69 # define mktime my_mktime
70 #endif /* DEBUG */
72 #ifndef __P
73 # if defined __GNUC__ || (defined __STDC__ && __STDC__)
74 # define __P(args) args
75 # else
76 # define __P(args) ()
77 # endif /* GCC. */
78 #endif /* Not __P. */
80 #ifndef CHAR_BIT
81 # define CHAR_BIT 8
82 #endif
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)))
92 #ifndef INT_MIN
93 # define INT_MIN TYPE_MINIMUM (int)
94 #endif
95 #ifndef INT_MAX
96 # define INT_MAX TYPE_MAXIMUM (int)
97 #endif
99 #ifndef TIME_T_MIN
100 # define TIME_T_MIN TYPE_MINIMUM (time_t)
101 #endif
102 #ifndef TIME_T_MAX
103 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
104 #endif
106 #define TM_YEAR_BASE 1900
107 #define EPOCH_YEAR 1970
109 #ifndef __isleap
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))
114 #endif
116 /* How many days come before each month (0-12). */
117 const unsigned short int __mon_yday[2][13] =
119 /* Normal years. */
120 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
121 /* Leap years. */
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 *,
126 struct tm *)),
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 *),
131 time_t *));
134 #ifdef _LIBC
135 # define localtime_r __localtime_r
136 #else
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 *));
140 static struct tm *
141 my_mktime_localtime_r (t, tp)
142 const time_t *t;
143 struct tm *tp;
145 # ifdef localtime_r
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
150 localtime_r. */
151 return localtime_r (t, tp);
152 # undef localtime_r
153 # else /* ! defined (localtime_r) */
154 /* Approximate localtime_r as best we can in its absence. */
155 struct tm *l = localtime (t);
156 if (! l)
157 return 0;
158 *tp = *l;
159 return tp;
160 # endif /* ! defined localtime_r */
162 # define localtime_r my_mktime_localtime_r
163 # endif /* HAVE_LOCALTIME_R == defined localtime_r */
164 #endif /* ! _LIBC */
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. */
173 static time_t
174 ydhms_tm_diff (year, yday, hour, min, sec, tp)
175 int year, yday, hour, min, sec;
176 const struct tm *tp;
178 if (!tp)
179 return 1;
180 else
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. */
207 time_t
208 mktime (tp)
209 struct tm *tp;
211 #ifdef _LIBC
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. */
215 __tzset ();
216 #endif
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. */
224 static struct tm *
225 ranged_convert (convert, t, tp)
226 struct tm *(*convert) __P ((const time_t *, struct tm *));
227 time_t *t;
228 struct tm *tp;
230 struct tm *r;
232 if (! (r = (*convert) (t, tp)) && *t)
234 time_t bad = *t;
235 time_t ok = 0;
236 struct tm tm;
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
240 they differ by 1. */
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)))
248 tm = *r;
249 ok = mid;
251 else
252 bad = mid;
255 if (!r && ok)
257 /* The last conversion attempt failed;
258 revert to the most recent successful attempt. */
259 *t = ok;
260 *tp = tm;
261 r = tp;
265 return r;
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. */
274 time_t
275 __mktime_internal (tp, convert, offset)
276 struct tm *tp;
277 struct tm *(*convert) __P ((const time_t *, struct tm *));
278 time_t *offset;
280 time_t t, dt, t0, t1, t2;
281 struct tm tm;
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])
314 + mday - 1);
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. */
320 if (sec < 0)
321 sec = 0;
322 if (59 < sec)
323 sec = 59;
324 #endif
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. */
347 break;
348 else if (--remaining_probes == 0)
349 return -1;
351 /* If we have a match, check whether tm.tm_isdst has the requested
352 value, if any. */
353 if (dt == 0 && isdst >= 0 && isdst != tm.tm_isdst)
355 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
356 if (dst_diff)
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;
367 struct tm otm;
368 struct tm tmptm;
370 otm.tm_isdst = -1;
372 while (--remaining_probes != 0)
374 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
375 ranged_convert (convert, &ot,
376 &tmptm)))
377 || tmptm.tm_isdst != isdst)
378 break;
380 otm = tmptm;
381 ot += dt;
382 if (ot == t)
383 break; /* Avoid a redundant probe. */
386 if (otm.tm_isdst != -1)
388 t = ot;
389 tm = otm;
394 *offset = t - t0;
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))
403 return -1;
405 #endif
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))
428 return -1;
431 *tp = tm;
432 return t;
435 #ifdef weak_alias
436 weak_alias (mktime, timelocal)
437 #endif
439 #if DEBUG
441 static int
442 not_equal_tm (a, b)
443 struct tm *a;
444 struct tm *b;
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));
457 static void
458 print_tm (tp)
459 struct tm *tp;
461 if (tp)
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);
466 else
467 printf ("0");
470 static int
471 check_result (tk, tmk, tl, lt)
472 time_t tk;
473 struct tm tmk;
474 time_t tl;
475 struct tm *lt;
477 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
479 printf ("mktime (");
480 print_tm (&tmk);
481 printf (")\nyields (");
482 print_tm (lt);
483 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
484 return 1;
487 return 0;
491 main (argc, argv)
492 int argc;
493 char **argv;
495 int status = 0;
496 struct tm tm, tmk, tml;
497 struct tm *lt;
498 time_t tk, tl;
499 char trailer;
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)
504 == 3)
505 && (sscanf (argv[2], "%d:%d:%d%c",
506 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
507 == 3))
509 tm.tm_year -= TM_YEAR_BASE;
510 tm.tm_mon--;
511 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
512 tmk = tm;
513 tl = mktime (&tmk);
514 lt = localtime (&tl);
515 if (lt)
517 tml = *lt;
518 lt = &tml;
520 printf ("mktime returns %ld == ", (long) tl);
521 print_tm (&tmk);
522 printf ("\n");
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]);
531 if (argc == 4)
532 for (tl = from; tl <= to; tl += by)
534 lt = localtime (&tl);
535 if (lt)
537 tmk = tml = *lt;
538 tk = mktime (&tmk);
539 status |= check_result (tk, tmk, tl, tml);
541 else
543 printf ("localtime (%ld) yields 0\n", (long) tl);
544 status = 1;
547 else
548 for (tl = from; tl <= to; tl += by)
550 /* Null benchmark. */
551 lt = localtime (&tl);
552 if (lt)
554 tmk = tml = *lt;
555 tk = tl;
556 status |= check_result (tk, tmk, tl, tml);
558 else
560 printf ("localtime (%ld) yields 0\n", (long) tl);
561 status = 1;
565 else
566 printf ("Usage:\
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]);
572 return status;
575 #endif /* DEBUG */
578 Local Variables:
579 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
580 End: