1 /* mktime: convert a `struct tm' to a time_t value
2 Copyright (C) 1993-1997, 1998 Free Software Foundation, Inc.
3 Contributed by Paul Eggert (eggert@twinsun.com).
5 NOTE: The canonical source of this file is maintained with the GNU C Library.
6 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 /* Define this to have a standalone program to test this implementation of
31 /* Some systems need this in order to declare localtime_r properly. */
37 # define HAVE_LIMITS_H 1
38 # define HAVE_LOCALTIME_R 1
39 # define STDC_HEADERS 1
42 /* Assume that leap seconds are possible, unless told otherwise.
43 If the host has a `zic' command with a `-L leapsecondfilename' option,
44 then it supports leap seconds; otherwise it probably doesn't. */
45 #ifndef LEAP_SECONDS_POSSIBLE
46 # define LEAP_SECONDS_POSSIBLE 1
49 #include <sys/types.h> /* Some systems define `time_t' here. */
61 /* Make it work even if the system's libc has its own mktime routine. */
62 # define mktime my_mktime
66 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
67 # define __P(args) args
77 /* The extra casts work around common compiler bugs. */
78 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
79 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
80 It is necessary at least when t == time_t. */
81 #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
82 ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
83 #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
86 # define INT_MIN TYPE_MINIMUM (int)
89 # define INT_MAX TYPE_MAXIMUM (int)
93 # define TIME_T_MIN TYPE_MINIMUM (time_t)
96 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
99 #define TM_YEAR_BASE 1900
100 #define EPOCH_YEAR 1970
103 /* Nonzero if YEAR is a leap year (every 4 years,
104 except every 100th isn't, and every 400th is). */
105 # define __isleap(year) \
106 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
109 /* How many days come before each month (0-12). */
110 const unsigned short int __mon_yday[2][13] =
113 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
115 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
118 static struct tm *ranged_convert __P ((struct tm *(*) __P ((const time_t *,
120 time_t *, struct tm *));
121 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
122 time_t __mktime_internal __P ((struct tm *,
123 struct tm *(*) (const time_t *, struct tm *),
128 # define localtime_r __localtime_r
130 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
131 /* Approximate localtime_r as best we can in its absence. */
132 # define localtime_r my_mktime_localtime_r
133 static struct tm *localtime_r __P ((const time_t *, struct tm *));
139 struct tm *l = localtime (t);
145 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
149 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
150 measured in seconds, ignoring leap seconds.
151 YEAR uses the same numbering as TM->tm_year.
152 All values are in range, except possibly YEAR.
153 If TP is null, return a nonzero value.
154 If overflow occurs, yield the low order bits of the correct answer. */
156 ydhms_tm_diff (year, yday, hour, min, sec, tp)
157 int year, yday, hour, min, sec;
164 /* Compute intervening leap days correctly even if year is negative.
165 Take care to avoid int overflow. time_t overflow is OK, since
166 only the low order bits of the correct time_t answer are needed.
167 Don't convert to time_t until after all divisions are done, since
168 time_t might be unsigned. */
169 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
170 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
171 int a100 = a4 / 25 - (a4 % 25 < 0);
172 int b100 = b4 / 25 - (b4 % 25 < 0);
173 int a400 = a100 >> 2;
174 int b400 = b100 >> 2;
175 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
176 time_t years = year - (time_t) tp->tm_year;
177 time_t days = (365 * years + intervening_leap_days
178 + (yday - tp->tm_yday));
179 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
180 + (min - tp->tm_min))
181 + (sec - tp->tm_sec));
186 static time_t localtime_offset;
188 /* Convert *TP to a time_t value. */
194 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
195 time zone names contained in the external variable `tzname' shall
196 be set as if the tzset() function had been called. */
200 return __mktime_internal (tp, localtime_r, &localtime_offset);
203 /* Use CONVERT to convert *T to a broken down time in *TP.
204 If *T is out of range for conversion, adjust it so that
205 it is the nearest in-range value and then convert that. */
207 ranged_convert (convert, t, tp)
208 struct tm *(*convert) __P ((const time_t *, struct tm *));
214 if (! (r = (*convert) (t, tp)) && *t)
220 /* BAD is a known unconvertible time_t, and OK is a known good one.
221 Use binary search to narrow the range between BAD and OK until
223 while (bad != ok + (bad < 0 ? -1 : 1))
225 time_t mid = *t = (bad < 0
226 ? bad + ((ok - bad) >> 1)
227 : ok + ((bad - ok) >> 1));
228 if ((r = (*convert) (t, tp)))
239 /* The last conversion attempt failed;
240 revert to the most recent successful attempt. */
251 /* Convert *TP to a time_t value, inverting
252 the monotonic and mostly-unit-linear conversion function CONVERT.
253 Use *OFFSET to keep track of a guess at the offset of the result,
254 compared to what the result would be for UTC without leap seconds.
255 If *OFFSET's guess is correct, only one CONVERT call is needed. */
257 __mktime_internal (tp, convert, offset)
259 struct tm *(*convert) __P ((const time_t *, struct tm *));
265 /* The maximum number of probes (calls to CONVERT) should be enough
266 to handle any combinations of time zone rule changes, solar time,
267 and leap seconds. POSIX.1 prohibits leap seconds, but some hosts
269 int remaining_probes = 4;
271 /* Time requested. Copy it in case CONVERT modifies *TP; this can
272 occur if TP is localtime's returned value and CONVERT is localtime. */
273 int sec = tp->tm_sec;
274 int min = tp->tm_min;
275 int hour = tp->tm_hour;
276 int mday = tp->tm_mday;
277 int mon = tp->tm_mon;
278 int year_requested = tp->tm_year;
279 int isdst = tp->tm_isdst;
281 /* Ensure that mon is in range, and set year accordingly. */
282 int mon_remainder = mon % 12;
283 int negative_mon_remainder = mon_remainder < 0;
284 int mon_years = mon / 12 - negative_mon_remainder;
285 int year = year_requested + mon_years;
287 /* The other values need not be in range:
288 the remaining code handles minor overflows correctly,
289 assuming int and time_t arithmetic wraps around.
290 Major overflows are caught at the end. */
292 /* Calculate day of year from year, month, and day of month.
293 The result need not be in range. */
294 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
295 [mon_remainder + 12 * negative_mon_remainder])
298 int sec_requested = sec;
299 #if LEAP_SECONDS_POSSIBLE
300 /* Handle out-of-range seconds specially,
301 since ydhms_tm_diff assumes every minute has 60 seconds. */
308 /* Invert CONVERT by probing. First assume the same offset as last time.
309 Then repeatedly use the error to improve the guess. */
311 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
312 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
313 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
315 for (t = t0 + *offset;
316 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
317 ranged_convert (convert, &t, &tm)));
319 if (--remaining_probes == 0)
322 /* Check whether tm.tm_isdst has the requested value, if any. */
323 if (0 <= isdst && 0 <= tm.tm_isdst)
325 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
328 /* Move two hours in the direction indicated by the disagreement,
329 probe some more, and switch to a new time if found.
330 The largest known fallback due to daylight savings is two hours:
331 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
332 time_t ot = t - 2 * 60 * 60 * dst_diff;
333 while (--remaining_probes != 0)
336 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
337 ranged_convert (convert, &ot, &otm))))
344 break; /* Avoid a redundant probe. */
351 #if LEAP_SECONDS_POSSIBLE
352 if (sec_requested != tm.tm_sec)
354 /* Adjust time to reflect the tm_sec requested, not the normalized value.
355 Also, repair any damage from a false match due to a leap second. */
356 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
357 if (! (*convert) (&t, &tm))
362 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
364 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
365 so check for major overflows. A gross check suffices,
366 since if t has overflowed, it is off by a multiple of
367 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
368 the difference that is bounded by a small value. */
370 double dyear = (double) year_requested + mon_years - tm.tm_year;
371 double dday = 366 * dyear + mday;
372 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
374 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
375 correct results, ie., it erroneously gives a positive value
376 of 715827882. Setting a variable first then doing math on it
377 seems to work. (ghazi@caip.rutgers.edu) */
379 const time_t time_t_max = TIME_T_MAX;
380 const time_t time_t_min = TIME_T_MIN;
382 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
391 weak_alias (mktime, timelocal)
401 return ((a->tm_sec ^ b->tm_sec)
402 | (a->tm_min ^ b->tm_min)
403 | (a->tm_hour ^ b->tm_hour)
404 | (a->tm_mday ^ b->tm_mday)
405 | (a->tm_mon ^ b->tm_mon)
406 | (a->tm_year ^ b->tm_year)
407 | (a->tm_mday ^ b->tm_mday)
408 | (a->tm_yday ^ b->tm_yday)
409 | (a->tm_isdst ^ b->tm_isdst));
417 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
418 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
419 tp->tm_hour, tp->tm_min, tp->tm_sec,
420 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
426 check_result (tk, tmk, tl, lt)
432 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
436 printf (")\nyields (");
438 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
451 struct tm tm, tmk, tml;
456 if ((argc == 3 || argc == 4)
457 && (sscanf (argv[1], "%d-%d-%d%c",
458 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
460 && (sscanf (argv[2], "%d:%d:%d%c",
461 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
464 tm.tm_year -= TM_YEAR_BASE;
466 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
469 lt = localtime (&tl);
475 printf ("mktime returns %ld == ", (long) tl);
478 status = check_result (tl, tmk, tl, lt);
480 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
482 time_t from = atol (argv[1]);
483 time_t by = atol (argv[2]);
484 time_t to = atol (argv[3]);
487 for (tl = from; tl <= to; tl += by)
489 lt = localtime (&tl);
494 status |= check_result (tk, tmk, tl, tml);
498 printf ("localtime (%ld) yields 0\n", (long) tl);
503 for (tl = from; tl <= to; tl += by)
505 /* Null benchmark. */
506 lt = localtime (&tl);
511 status |= check_result (tk, tmk, tl, tml);
515 printf ("localtime (%ld) yields 0\n", (long) tl);
522 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
523 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
524 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
525 argv[0], argv[0], argv[0]);
534 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"