(M68*:*:R3V[567]*:*): Use uppercase 'M'.
[glibc.git] / time / mktime.c
blob7fa5ccb23a26f5e69779de1dee1643b5cdf05179
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
22 mktime. */
23 /* #define DEBUG 1 */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
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
34 #endif
36 #include <sys/types.h> /* Some systems define `time_t' here. */
37 #include <time.h>
39 #if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
40 #include <limits.h>
41 #endif
43 #if DEBUG
44 #include <stdio.h>
45 #if __STDC__ || __GNU_LIBRARY__ || STDC_HEADERS
46 #include <stdlib.h>
47 #endif
48 /* Make it work even if the system's libc has its own mktime routine. */
49 #define mktime my_mktime
50 #endif /* DEBUG */
52 #ifndef __P
53 #if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
54 #define __P(args) args
55 #else
56 #define __P(args) ()
57 #endif /* GCC. */
58 #endif /* Not __P. */
60 #ifndef CHAR_BIT
61 #define CHAR_BIT 8
62 #endif
64 #ifndef INT_MIN
65 #define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
66 #endif
67 #ifndef INT_MAX
68 #define INT_MAX (~0 - INT_MIN)
69 #endif
71 #ifndef TIME_T_MIN
72 #define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
73 : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
74 #endif
75 #ifndef TIME_T_MAX
76 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
77 #endif
79 #define TM_YEAR_BASE 1900
80 #define EPOCH_YEAR 1970
82 #ifndef __isleap
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))
87 #endif
89 /* How many days come before each month (0-12). */
90 const unsigned short int __mon_yday[2][13] =
92 /* Normal years. */
93 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
94 /* Leap years. */
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 *),
101 time_t *));
104 #if ! HAVE_LOCALTIME_R && ! defined (localtime_r)
105 #ifdef _LIBC
106 #define localtime_r __localtime_r
107 #else
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 *));
111 static struct tm *
112 localtime_r (t, tp)
113 const time_t *t;
114 struct tm *tp;
116 struct tm *l = localtime (t);
117 if (! l)
118 return 0;
119 *tp = *l;
120 return tp;
122 #endif /* ! _LIBC */
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. */
131 static time_t
132 ydhms_tm_diff (year, yday, hour, min, sec, tp)
133 int year, yday, hour, min, sec;
134 const struct tm *tp;
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. */
160 time_t
161 mktime (tp)
162 struct tm *tp;
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. */
172 time_t
173 __mktime_internal (tp, convert, offset)
174 struct tm *tp;
175 struct tm *(*convert) __P ((const time_t *, struct tm *));
176 time_t *offset;
178 time_t t, dt, t0;
179 struct tm 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
184 have them anyway. */
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])
212 + mday - 1);
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;
218 if (sec < 0)
219 sec = 0;
220 if (59 < sec)
221 sec = 59;
222 #endif
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)));
233 t += dt)
234 if (--remaining_probes == 0)
235 return -1;
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);
241 if (dst_diff)
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)
250 struct tm otm;
251 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
252 (*convert) (&ot, &otm))))
254 t = ot;
255 tm = otm;
256 break;
258 if ((ot += dt) == t)
259 break; /* Avoid a redundant probe. */
264 *offset = t - t0;
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);
274 #endif
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))
289 return -1;
292 *tp = tm;
293 return t;
296 #ifdef weak_alias
297 weak_alias (mktime, timelocal)
298 #endif
300 #if DEBUG
302 static int
303 not_equal_tm (a, b)
304 struct tm *a;
305 struct tm *b;
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));
318 static void
319 print_tm (tp)
320 struct tm *tp;
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);
328 static int
329 check_result (tk, tmk, tl, tml)
330 time_t tk;
331 struct tm tmk;
332 time_t tl;
333 struct tm tml;
335 if (tk != tl || not_equal_tm (&tmk, &tml))
337 printf ("mktime (");
338 print_tm (&tmk);
339 printf (")\nyields (");
340 print_tm (&tml);
341 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
342 return 1;
345 return 0;
349 main (argc, argv)
350 int argc;
351 char **argv;
353 int status = 0;
354 struct tm tm, tmk, tml;
355 time_t tk, tl;
356 char trailer;
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)
361 == 3)
362 && (sscanf (argv[2], "%d:%d:%d%c",
363 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
364 == 3))
366 tm.tm_year -= TM_YEAR_BASE;
367 tm.tm_mon--;
368 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
369 tmk = tm;
370 tl = mktime (&tmk);
371 tml = *localtime (&tl);
372 printf ("mktime returns %ld == ", (long) tl);
373 print_tm (&tmk);
374 printf ("\n");
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]);
383 if (argc == 4)
384 for (tl = from; tl <= to; tl += by)
386 tml = *localtime (&tl);
387 tmk = tml;
388 tk = mktime (&tmk);
389 status |= check_result (tk, tmk, tl, tml);
391 else
392 for (tl = from; tl <= to; tl += by)
394 /* Null benchmark. */
395 tml = *localtime (&tl);
396 tmk = tml;
397 tk = tl;
398 status |= check_result (tk, tmk, tl, tml);
401 else
402 printf ("Usage:\
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]);
408 return status;
411 #endif /* DEBUG */
414 Local Variables:
415 compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"
416 End: