1 /* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
2 Contributed by Paul Eggert (eggert@twinsun.com).
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 Cambridge, MA 02139, USA. */
21 /* Define this to have a standalone program to test this implementation of
29 /* Assume that leap seconds are possible, unless told otherwise.
30 If the host has a `zic' command with a `-L leapsecondfilename' option,
31 then it supports leap seconds; otherwise it probably doesn't. */
32 #ifndef LEAP_SECONDS_POSSIBLE
33 #define LEAP_SECONDS_POSSIBLE 1
36 #include <sys/types.h> /* Some systems define `time_t' here. */
39 #if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
45 #if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
48 /* Make it work even if the system's libc has its own mktime routine. */
49 #define mktime my_mktime
53 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
54 #define __P(args) args
65 #define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
68 #define INT_MAX (~0 - INT_MIN)
72 #define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
73 : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
76 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
79 #define TM_YEAR_BASE 1900
80 #define EPOCH_YEAR 1970
83 /* Nonzero if YEAR is a leap year (every 4 years,
84 except every 100th isn't, and every 400th is). */
85 #define __isleap(year) \
86 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
89 /* How many days come before each month (0-12). */
90 const unsigned short int __mon_yday[2][13] =
93 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
95 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
98 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
99 time_t __mktime_internal __P ((struct tm *,
100 struct tm *(*) (const time_t *, struct tm *),
104 #if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
106 #define localtime_r __localtime_r
108 /* Approximate localtime_r as best we can in its absence. */
109 #define localtime_r my_localtime_r
110 static struct tm *localtime_r __P ((const time_t *, struct tm *));
116 struct tm *l = localtime (t);
123 #endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
126 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
127 measured in seconds, ignoring leap seconds.
128 YEAR uses the same numbering as TM->tm_year.
129 All values are in range, except possibly YEAR.
130 If overflow occurs, yield the low order bits of the correct answer. */
132 ydhms_tm_diff (year, yday, hour, min, sec, tp)
133 int year, yday, hour, min, sec;
136 /* Compute intervening leap days correctly even if year is negative.
137 Take care to avoid int overflow. time_t overflow is OK, since
138 only the low order bits of the correct time_t answer are needed.
139 Don't convert to time_t until after all divisions are done, since
140 time_t might be unsigned. */
141 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
142 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
143 int a100 = a4 / 25 - (a4 % 25 < 0);
144 int b100 = b4 / 25 - (b4 % 25 < 0);
145 int a400 = a100 >> 2;
146 int b400 = b100 >> 2;
147 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
148 time_t years = year - (time_t) tp->tm_year;
149 time_t days = (365 * years + intervening_leap_days
150 + (yday - tp->tm_yday));
151 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
152 + (min - tp->tm_min))
153 + (sec - tp->tm_sec));
157 static time_t localtime_offset;
159 /* Convert *TP to a time_t value. */
164 return __mktime_internal (tp, localtime_r, &localtime_offset);
167 /* Convert *TP to a time_t value, inverting
168 the monotonic and mostly-unit-linear conversion function CONVERT.
169 Use *OFFSET to keep track of a guess at the offset of the result,
170 compared to what the result would be for UTC without leap seconds.
171 If *OFFSET's guess is correct, only one CONVERT call is needed. */
173 __mktime_internal (tp, convert, offset)
175 struct tm *(*convert) __P ((const time_t *, struct tm *));
181 /* The maximum number of probes (calls to CONVERT) should be enough
182 to handle any combinations of time zone rule changes, solar time,
183 and leap seconds. Posix.1 prohibits leap seconds, but some hosts
185 int remaining_probes = 4;
187 /* Time requested. Copy it in case CONVERT modifies *TP; this can
188 occur if TP is localtime's returned value and CONVERT is localtime. */
189 int sec = tp->tm_sec;
190 int min = tp->tm_min;
191 int hour = tp->tm_hour;
192 int mday = tp->tm_mday;
193 int mon = tp->tm_mon;
194 int year_requested = tp->tm_year;
195 int isdst = tp->tm_isdst;
197 /* Ensure that mon is in range, and set year accordingly. */
198 int mon_remainder = mon % 12;
199 int negative_mon_remainder = mon_remainder < 0;
200 int mon_years = mon / 12 - negative_mon_remainder;
201 int year = year_requested + mon_years;
203 /* The other values need not be in range:
204 the remaining code handles minor overflows correctly,
205 assuming int and time_t arithmetic wraps around.
206 Major overflows are caught at the end. */
208 /* Calculate day of year from year, month, and day of month.
209 The result need not be in range. */
210 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
211 [mon_remainder + 12 * negative_mon_remainder])
214 #if LEAP_SECONDS_POSSIBLE
215 /* Handle out-of-range seconds specially,
216 since ydhms_tm_diff assumes every minute has 60 seconds. */
217 int sec_requested = sec;
224 /* Invert CONVERT by probing. First assume the same offset as last time.
225 Then repeatedly use the error to improve the guess. */
227 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
228 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
229 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
231 for (t = t0 + *offset;
232 (dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
234 if (--remaining_probes == 0)
237 /* Check whether tm.tm_isdst has the requested value, if any. */
238 if (0 <= isdst && 0 <= tm.tm_isdst)
240 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
243 /* Move two hours in the direction indicated by the disagreement,
244 probe some more, and switch to a new time if found.
245 The largest known fallback due to daylight savings is two hours:
246 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
247 time_t ot = t - 2 * 60 * 60 * dst_diff;
248 while (--remaining_probes != 0)
251 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
252 (*convert) (&ot, &otm))))
259 break; /* Avoid a redundant probe. */
266 #if LEAP_SECONDS_POSSIBLE
267 if (sec_requested != tm.tm_sec)
269 /* Adjust time to reflect the tm_sec requested, not the normalized value.
270 Also, repair any damage from a false match due to a leap second. */
271 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
272 (*convert) (&t, &tm);
276 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
278 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
279 so check for major overflows. A gross check suffices,
280 since if t has overflowed, it is off by a multiple of
281 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
282 the difference that is bounded by a small value. */
284 double dyear = (double) year_requested + mon_years - tm.tm_year;
285 double dday = 366 * dyear + mday;
286 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
288 if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
297 weak_alias (mktime, timelocal)
307 return ((a->tm_sec ^ b->tm_sec)
308 | (a->tm_min ^ b->tm_min)
309 | (a->tm_hour ^ b->tm_hour)
310 | (a->tm_mday ^ b->tm_mday)
311 | (a->tm_mon ^ b->tm_mon)
312 | (a->tm_year ^ b->tm_year)
313 | (a->tm_mday ^ b->tm_mday)
314 | (a->tm_yday ^ b->tm_yday)
315 | (a->tm_isdst ^ b->tm_isdst));
322 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
323 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
324 tp->tm_hour, tp->tm_min, tp->tm_sec,
325 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
329 check_result (tk, tmk, tl, tml)
335 if (tk != tl || not_equal_tm (&tmk, &tml))
339 printf (")\nyields (");
341 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
354 struct tm tm, tmk, tml;
358 if ((argc == 3 || argc == 4)
359 && (sscanf (argv[1], "%d-%d-%d%c",
360 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
362 && (sscanf (argv[2], "%d:%d:%d%c",
363 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
366 tm.tm_year -= TM_YEAR_BASE;
368 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
371 tml = *localtime (&tl);
372 printf ("mktime returns %ld == ", (long) tl);
375 status = check_result (tl, tmk, tl, tml);
377 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
379 time_t from = atol (argv[1]);
380 time_t by = atol (argv[2]);
381 time_t to = atol (argv[3]);
384 for (tl = from; tl <= to; tl += by)
386 tml = *localtime (&tl);
389 status |= check_result (tk, tmk, tl, tml);
392 for (tl = from; tl <= to; tl += by)
394 /* Null benchmark. */
395 tml = *localtime (&tl);
398 status |= check_result (tk, tmk, tl, tml);
403 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
404 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
405 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
406 argv[0], argv[0], argv[0]);
415 compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"