Update.
[glibc.git] / time / mktime.c
blobf5a4f61f67e0733f4deb9548833e85f9572fe4a4
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 need this in order to declare localtime_r properly. */
29 #ifndef _REENTRANT
30 # define _REENTRANT 1
31 #endif
33 #ifdef _LIBC
34 # define HAVE_LIMITS_H 1
35 # define HAVE_LOCALTIME_R 1
36 # define STDC_HEADERS 1
37 #endif
39 /* Assume that leap seconds are possible, unless told otherwise.
40 If the host has a `zic' command with a `-L leapsecondfilename' option,
41 then it supports leap seconds; otherwise it probably doesn't. */
42 #ifndef LEAP_SECONDS_POSSIBLE
43 # define LEAP_SECONDS_POSSIBLE 1
44 #endif
46 #include <sys/types.h> /* Some systems define `time_t' here. */
47 #include <time.h>
49 #if HAVE_LIMITS_H
50 # include <limits.h>
51 #endif
53 #if DEBUG
54 # include <stdio.h>
55 # if STDC_HEADERS
56 # include <stdlib.h>
57 # endif
58 /* Make it work even if the system's libc has its own mktime routine. */
59 # define mktime my_mktime
60 #endif /* DEBUG */
62 #ifndef __P
63 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
64 # define __P(args) args
65 # else
66 # define __P(args) ()
67 # endif /* GCC. */
68 #endif /* Not __P. */
70 #ifndef CHAR_BIT
71 # define CHAR_BIT 8
72 #endif
74 /* The extra casts work around common compiler bugs. */
75 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
76 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
77 It is necessary at least when t == time_t. */
78 #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
79 ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
80 #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
82 #ifndef INT_MIN
83 # define INT_MIN TYPE_MINIMUM (int)
84 #endif
85 #ifndef INT_MAX
86 # define INT_MAX TYPE_MAXIMUM (int)
87 #endif
89 #ifndef TIME_T_MIN
90 # define TIME_T_MIN TYPE_MINIMUM (time_t)
91 #endif
92 #ifndef TIME_T_MAX
93 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
94 #endif
96 #define TM_YEAR_BASE 1900
97 #define EPOCH_YEAR 1970
99 #ifndef __isleap
100 /* Nonzero if YEAR is a leap year (every 4 years,
101 except every 100th isn't, and every 400th is). */
102 # define __isleap(year) \
103 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
104 #endif
106 /* How many days come before each month (0-12). */
107 const unsigned short int __mon_yday[2][13] =
109 /* Normal years. */
110 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
111 /* Leap years. */
112 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
115 static struct tm *ranged_convert __P ((struct tm *(*) __P ((const time_t *,
116 struct tm *)),
117 time_t *, struct tm *));
118 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
119 time_t __mktime_internal __P ((struct tm *,
120 struct tm *(*) (const time_t *, struct tm *),
121 time_t *));
124 #ifdef _LIBC
125 # define localtime_r __localtime_r
126 #else
127 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
128 /* Approximate localtime_r as best we can in its absence. */
129 # define localtime_r my_mktime_localtime_r
130 static struct tm *localtime_r __P ((const time_t *, struct tm *));
131 static struct tm *
132 localtime_r (t, tp)
133 const time_t *t;
134 struct tm *tp;
136 struct tm *l = localtime (t);
137 if (! l)
138 return 0;
139 *tp = *l;
140 return tp;
142 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
143 #endif /* ! _LIBC */
146 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
147 measured in seconds, ignoring leap seconds.
148 YEAR uses the same numbering as TM->tm_year.
149 All values are in range, except possibly YEAR.
150 If TP is null, return a nonzero value.
151 If overflow occurs, yield the low order bits of the correct answer. */
152 static time_t
153 ydhms_tm_diff (year, yday, hour, min, sec, tp)
154 int year, yday, hour, min, sec;
155 const struct tm *tp;
157 if (!tp)
158 return 1;
159 else
161 /* Compute intervening leap days correctly even if year is negative.
162 Take care to avoid int overflow. time_t overflow is OK, since
163 only the low order bits of the correct time_t answer are needed.
164 Don't convert to time_t until after all divisions are done, since
165 time_t might be unsigned. */
166 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
167 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
168 int a100 = a4 / 25 - (a4 % 25 < 0);
169 int b100 = b4 / 25 - (b4 % 25 < 0);
170 int a400 = a100 >> 2;
171 int b400 = b100 >> 2;
172 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
173 time_t years = year - (time_t) tp->tm_year;
174 time_t days = (365 * years + intervening_leap_days
175 + (yday - tp->tm_yday));
176 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
177 + (min - tp->tm_min))
178 + (sec - tp->tm_sec));
183 static time_t localtime_offset;
185 /* Convert *TP to a time_t value. */
186 time_t
187 mktime (tp)
188 struct tm *tp;
190 #ifdef _LIBC
191 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
192 time zone names contained in the external variable `tzname' shall
193 be set as if the tzset() function had been called. */
194 __tzset ();
195 #endif
197 return __mktime_internal (tp, localtime_r, &localtime_offset);
200 /* Use CONVERT to convert *T to a broken down time in *TP.
201 If *T is out of range for conversion, adjust it so that
202 it is the nearest in-range value and then convert that. */
203 static struct tm *
204 ranged_convert (convert, t, tp)
205 struct tm *(*convert) __P ((const time_t *, struct tm *));
206 time_t *t;
207 struct tm *tp;
209 struct tm *r;
211 if (! (r = (*convert) (t, tp)) && *t)
213 time_t bad = *t;
214 time_t ok = 0;
215 struct tm tm;
217 /* BAD is a known unconvertible time_t, and OK is a known good one.
218 Use binary search to narrow the range between BAD and OK until
219 they differ by 1. */
220 while (bad != ok + (bad < 0 ? -1 : 1))
222 time_t mid = *t = (bad < 0
223 ? bad + ((ok - bad) >> 1)
224 : ok + ((bad - ok) >> 1));
225 if ((r = (*convert) (t, tp)))
227 tm = *r;
228 ok = mid;
230 else
231 bad = mid;
234 if (!r && ok)
236 /* The last conversion attempt failed;
237 revert to the most recent successful attempt. */
238 *t = ok;
239 *tp = tm;
240 r = tp;
244 return r;
248 /* Convert *TP to a time_t value, inverting
249 the monotonic and mostly-unit-linear conversion function CONVERT.
250 Use *OFFSET to keep track of a guess at the offset of the result,
251 compared to what the result would be for UTC without leap seconds.
252 If *OFFSET's guess is correct, only one CONVERT call is needed. */
253 time_t
254 __mktime_internal (tp, convert, offset)
255 struct tm *tp;
256 struct tm *(*convert) __P ((const time_t *, struct tm *));
257 time_t *offset;
259 time_t t, dt, t0;
260 struct tm tm;
262 /* The maximum number of probes (calls to CONVERT) should be enough
263 to handle any combinations of time zone rule changes, solar time,
264 and leap seconds. POSIX.1 prohibits leap seconds, but some hosts
265 have them anyway. */
266 int remaining_probes = 4;
268 /* Time requested. Copy it in case CONVERT modifies *TP; this can
269 occur if TP is localtime's returned value and CONVERT is localtime. */
270 int sec = tp->tm_sec;
271 int min = tp->tm_min;
272 int hour = tp->tm_hour;
273 int mday = tp->tm_mday;
274 int mon = tp->tm_mon;
275 int year_requested = tp->tm_year;
276 int isdst = tp->tm_isdst;
278 /* Ensure that mon is in range, and set year accordingly. */
279 int mon_remainder = mon % 12;
280 int negative_mon_remainder = mon_remainder < 0;
281 int mon_years = mon / 12 - negative_mon_remainder;
282 int year = year_requested + mon_years;
284 /* The other values need not be in range:
285 the remaining code handles minor overflows correctly,
286 assuming int and time_t arithmetic wraps around.
287 Major overflows are caught at the end. */
289 /* Calculate day of year from year, month, and day of month.
290 The result need not be in range. */
291 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
292 [mon_remainder + 12 * negative_mon_remainder])
293 + mday - 1);
295 int sec_requested = sec;
296 #if LEAP_SECONDS_POSSIBLE
297 /* Handle out-of-range seconds specially,
298 since ydhms_tm_diff assumes every minute has 60 seconds. */
299 if (sec < 0)
300 sec = 0;
301 if (59 < sec)
302 sec = 59;
303 #endif
305 /* Invert CONVERT by probing. First assume the same offset as last time.
306 Then repeatedly use the error to improve the guess. */
308 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
309 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
310 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
312 for (t = t0 + *offset;
313 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
314 ranged_convert (convert, &t, &tm)));
315 t += dt)
316 if (--remaining_probes == 0)
317 return -1;
319 /* Check whether tm.tm_isdst has the requested value, if any. */
320 if (0 <= isdst && 0 <= tm.tm_isdst)
322 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
323 if (dst_diff)
325 /* Move two hours in the direction indicated by the disagreement,
326 probe some more, and switch to a new time if found.
327 The largest known fallback due to daylight savings is two hours:
328 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
329 time_t ot = t - 2 * 60 * 60 * dst_diff;
330 while (--remaining_probes != 0)
332 struct tm otm;
333 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
334 ranged_convert (convert, &ot, &otm))))
336 t = ot;
337 tm = otm;
338 break;
340 if ((ot += dt) == t)
341 break; /* Avoid a redundant probe. */
346 *offset = t - t0;
348 #if LEAP_SECONDS_POSSIBLE
349 if (sec_requested != tm.tm_sec)
351 /* Adjust time to reflect the tm_sec requested, not the normalized value.
352 Also, repair any damage from a false match due to a leap second. */
353 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
354 if (! (*convert) (&t, &tm))
355 return -1;
357 #endif
359 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
361 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
362 so check for major overflows. A gross check suffices,
363 since if t has overflowed, it is off by a multiple of
364 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
365 the difference that is bounded by a small value. */
367 double dyear = (double) year_requested + mon_years - tm.tm_year;
368 double dday = 366 * dyear + mday;
369 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
371 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
372 correct results, ie., it erroneously gives a positive value
373 of 715827882. Setting a variable first then doing math on it
374 seems to work. (ghazi@caip.rutgers.edu) */
376 const time_t time_t_max = TIME_T_MAX;
377 const time_t time_t_min = TIME_T_MIN;
379 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
380 return -1;
383 *tp = tm;
384 return t;
387 #ifdef weak_alias
388 weak_alias (mktime, timelocal)
389 #endif
391 #if DEBUG
393 static int
394 not_equal_tm (a, b)
395 struct tm *a;
396 struct tm *b;
398 return ((a->tm_sec ^ b->tm_sec)
399 | (a->tm_min ^ b->tm_min)
400 | (a->tm_hour ^ b->tm_hour)
401 | (a->tm_mday ^ b->tm_mday)
402 | (a->tm_mon ^ b->tm_mon)
403 | (a->tm_year ^ b->tm_year)
404 | (a->tm_mday ^ b->tm_mday)
405 | (a->tm_yday ^ b->tm_yday)
406 | (a->tm_isdst ^ b->tm_isdst));
409 static void
410 print_tm (tp)
411 struct tm *tp;
413 if (tp)
414 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
415 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
416 tp->tm_hour, tp->tm_min, tp->tm_sec,
417 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
418 else
419 printf ("0");
422 static int
423 check_result (tk, tmk, tl, lt)
424 time_t tk;
425 struct tm tmk;
426 time_t tl;
427 struct tm *lt;
429 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
431 printf ("mktime (");
432 print_tm (&tmk);
433 printf (")\nyields (");
434 print_tm (lt);
435 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
436 return 1;
439 return 0;
443 main (argc, argv)
444 int argc;
445 char **argv;
447 int status = 0;
448 struct tm tm, tmk, tml;
449 struct tm *lt;
450 time_t tk, tl;
451 char trailer;
453 if ((argc == 3 || argc == 4)
454 && (sscanf (argv[1], "%d-%d-%d%c",
455 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
456 == 3)
457 && (sscanf (argv[2], "%d:%d:%d%c",
458 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
459 == 3))
461 tm.tm_year -= TM_YEAR_BASE;
462 tm.tm_mon--;
463 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
464 tmk = tm;
465 tl = mktime (&tmk);
466 lt = localtime (&tl);
467 if (lt)
469 tml = *lt;
470 lt = &tml;
472 printf ("mktime returns %ld == ", (long) tl);
473 print_tm (&tmk);
474 printf ("\n");
475 status = check_result (tl, tmk, tl, lt);
477 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
479 time_t from = atol (argv[1]);
480 time_t by = atol (argv[2]);
481 time_t to = atol (argv[3]);
483 if (argc == 4)
484 for (tl = from; tl <= to; tl += by)
486 lt = localtime (&tl);
487 if (lt)
489 tmk = tml = *lt;
490 tk = mktime (&tmk);
491 status |= check_result (tk, tmk, tl, tml);
493 else
495 printf ("localtime (%ld) yields 0\n", (long) tl);
496 status = 1;
499 else
500 for (tl = from; tl <= to; tl += by)
502 /* Null benchmark. */
503 lt = localtime (&tl);
504 if (lt)
506 tmk = tml = *lt;
507 tk = tl;
508 status |= check_result (tk, tmk, tl, tml);
510 else
512 printf ("localtime (%ld) yields 0\n", (long) tl);
513 status = 1;
517 else
518 printf ("Usage:\
519 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
520 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
521 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
522 argv[0], argv[0], argv[0]);
524 return status;
527 #endif /* DEBUG */
530 Local Variables:
531 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
532 End: