(CHECK_FRAME, CHECK_LIVE_FRAME): Remove unused argument `i' in macros.
[bpt/emacs.git] / src / mktime.c
CommitLineData
68c45bf0
PE
1/* Convert a `struct tm' to a time_t value.
2 Copyright (C) 1993, 94, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
98f1928d
PE
3 Contributed by Paul Eggert (eggert@twinsun.com).
4
89752145 5 NOTE: The canonical source of this file is maintained with the GNU C Library.
06bd27fd 6 Bugs can be reported to bug-glibc@gnu.org.
98f1928d 7
89752145
PE
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
11 later version.
98f1928d 12
89752145
PE
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.
98f1928d 17
89752145
PE
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,
21 USA. */
98f1928d
PE
22
23/* Define this to have a standalone program to test this implementation of
24 mktime. */
25/* #define DEBUG 1 */
26
27#ifdef HAVE_CONFIG_H
6385ec2b 28# include <config.h>
98f1928d
PE
29#endif
30
31#ifdef _LIBC
32# define HAVE_LIMITS_H 1
98f1928d
PE
33# define STDC_HEADERS 1
34#endif
35
36/* Assume that leap seconds are possible, unless told otherwise.
37 If the host has a `zic' command with a `-L leapsecondfilename' option,
38 then it supports leap seconds; otherwise it probably doesn't. */
39#ifndef LEAP_SECONDS_POSSIBLE
6385ec2b 40# define LEAP_SECONDS_POSSIBLE 1
98f1928d
PE
41#endif
42
43#include <sys/types.h> /* Some systems define `time_t' here. */
44#include <time.h>
45
46#if HAVE_LIMITS_H
6385ec2b 47# include <limits.h>
98f1928d
PE
48#endif
49
50#if DEBUG
6385ec2b
PE
51# include <stdio.h>
52# if STDC_HEADERS
53# include <stdlib.h>
54# endif
98f1928d 55/* Make it work even if the system's libc has its own mktime routine. */
6385ec2b 56# define mktime my_mktime
98f1928d
PE
57#endif /* DEBUG */
58
59#ifndef __P
68c45bf0 60# if defined __GNUC__ || (defined __STDC__ && __STDC__)
6385ec2b
PE
61# define __P(args) args
62# else
63# define __P(args) ()
64# endif /* GCC. */
98f1928d
PE
65#endif /* Not __P. */
66
67#ifndef CHAR_BIT
6385ec2b 68# define CHAR_BIT 8
98f1928d
PE
69#endif
70
067cc4dc
UD
71/* The extra casts work around common compiler bugs. */
72#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
73/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
74 It is necessary at least when t == time_t. */
75#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
76 ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
06bd27fd 77#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
067cc4dc 78
98f1928d 79#ifndef INT_MIN
067cc4dc 80# define INT_MIN TYPE_MINIMUM (int)
98f1928d
PE
81#endif
82#ifndef INT_MAX
067cc4dc 83# define INT_MAX TYPE_MAXIMUM (int)
98f1928d
PE
84#endif
85
86#ifndef TIME_T_MIN
067cc4dc 87# define TIME_T_MIN TYPE_MINIMUM (time_t)
98f1928d
PE
88#endif
89#ifndef TIME_T_MAX
067cc4dc 90# define TIME_T_MAX TYPE_MAXIMUM (time_t)
98f1928d
PE
91#endif
92
93#define TM_YEAR_BASE 1900
94#define EPOCH_YEAR 1970
95
96#ifndef __isleap
97/* Nonzero if YEAR is a leap year (every 4 years,
98 except every 100th isn't, and every 400th is). */
6385ec2b 99# define __isleap(year) \
98f1928d
PE
100 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
101#endif
102
103/* How many days come before each month (0-12). */
104const unsigned short int __mon_yday[2][13] =
105 {
106 /* Normal years. */
107 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
108 /* Leap years. */
109 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
110 };
111
98f1928d
PE
112
113#ifdef _LIBC
68c45bf0 114# define my_mktime_localtime_r __localtime_r
98f1928d 115#else
68c45bf0
PE
116/* If we're a mktime substitute in a GNU program, then prefer
117 localtime to localtime_r, since many localtime_r implementations
118 are buggy. */
98f1928d 119static struct tm *
998e9f8c
DL
120my_mktime_localtime_r (t, tp)
121 const time_t *t;
122 struct tm *tp;
98f1928d
PE
123{
124 struct tm *l = localtime (t);
125 if (! l)
126 return 0;
127 *tp = *l;
128 return tp;
129}
98f1928d
PE
130#endif /* ! _LIBC */
131
132
133/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
134 measured in seconds, ignoring leap seconds.
135 YEAR uses the same numbering as TM->tm_year.
136 All values are in range, except possibly YEAR.
649e97a3 137 If TP is null, return a nonzero value.
98f1928d
PE
138 If overflow occurs, yield the low order bits of the correct answer. */
139static time_t
998e9f8c
DL
140ydhms_tm_diff (year, yday, hour, min, sec, tp)
141 int year, yday, hour, min, sec;
142 const struct tm *tp;
98f1928d 143{
649e97a3
UD
144 if (!tp)
145 return 1;
146 else
147 {
148 /* Compute intervening leap days correctly even if year is negative.
149 Take care to avoid int overflow. time_t overflow is OK, since
150 only the low order bits of the correct time_t answer are needed.
151 Don't convert to time_t until after all divisions are done, since
152 time_t might be unsigned. */
153 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
154 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
155 int a100 = a4 / 25 - (a4 % 25 < 0);
156 int b100 = b4 / 25 - (b4 % 25 < 0);
157 int a400 = a100 >> 2;
158 int b400 = b100 >> 2;
159 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
160 time_t years = year - (time_t) tp->tm_year;
161 time_t days = (365 * years + intervening_leap_days
162 + (yday - tp->tm_yday));
163 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
164 + (min - tp->tm_min))
165 + (sec - tp->tm_sec));
166 }
98f1928d
PE
167}
168
649e97a3
UD
169/* Use CONVERT to convert *T to a broken down time in *TP.
170 If *T is out of range for conversion, adjust it so that
171 it is the nearest in-range value and then convert that. */
172static struct tm *
998e9f8c
DL
173ranged_convert (convert, t, tp)
174#ifdef PROTOTYPES
175 struct tm *(*convert) (const time_t *, struct tm *);
176#else
177 struct tm *(*convert)();
178#endif
179 time_t *t;
180 struct tm *tp;
649e97a3
UD
181{
182 struct tm *r;
183
184 if (! (r = (*convert) (t, tp)) && *t)
185 {
186 time_t bad = *t;
187 time_t ok = 0;
188 struct tm tm;
189
190 /* BAD is a known unconvertible time_t, and OK is a known good one.
191 Use binary search to narrow the range between BAD and OK until
192 they differ by 1. */
193 while (bad != ok + (bad < 0 ? -1 : 1))
194 {
195 time_t mid = *t = (bad < 0
196 ? bad + ((ok - bad) >> 1)
197 : ok + ((bad - ok) >> 1));
198 if ((r = (*convert) (t, tp)))
199 {
200 tm = *r;
201 ok = mid;
202 }
203 else
204 bad = mid;
205 }
206
207 if (!r && ok)
208 {
209 /* The last conversion attempt failed;
210 revert to the most recent successful attempt. */
211 *t = ok;
212 *tp = tm;
213 r = tp;
214 }
215 }
216
217 return r;
218}
219
220
98f1928d
PE
221/* Convert *TP to a time_t value, inverting
222 the monotonic and mostly-unit-linear conversion function CONVERT.
223 Use *OFFSET to keep track of a guess at the offset of the result,
224 compared to what the result would be for UTC without leap seconds.
225 If *OFFSET's guess is correct, only one CONVERT call is needed. */
226time_t
998e9f8c
DL
227__mktime_internal (tp, convert, offset)
228 struct tm *tp;
229#ifdef PROTOTYPES
230 struct tm *(*convert) (const time_t *, struct tm *);
231#else
232 struct tm *(*convert)();
233#endif
234 time_t *offset;
98f1928d 235{
68c45bf0 236 time_t t, dt, t0, t1, t2;
98f1928d
PE
237 struct tm tm;
238
239 /* The maximum number of probes (calls to CONVERT) should be enough
240 to handle any combinations of time zone rule changes, solar time,
68c45bf0
PE
241 leap seconds, and oscillations around a spring-forward gap.
242 POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
243 int remaining_probes = 6;
98f1928d
PE
244
245 /* Time requested. Copy it in case CONVERT modifies *TP; this can
246 occur if TP is localtime's returned value and CONVERT is localtime. */
247 int sec = tp->tm_sec;
248 int min = tp->tm_min;
249 int hour = tp->tm_hour;
250 int mday = tp->tm_mday;
251 int mon = tp->tm_mon;
252 int year_requested = tp->tm_year;
253 int isdst = tp->tm_isdst;
254
255 /* Ensure that mon is in range, and set year accordingly. */
256 int mon_remainder = mon % 12;
257 int negative_mon_remainder = mon_remainder < 0;
258 int mon_years = mon / 12 - negative_mon_remainder;
259 int year = year_requested + mon_years;
260
261 /* The other values need not be in range:
262 the remaining code handles minor overflows correctly,
263 assuming int and time_t arithmetic wraps around.
264 Major overflows are caught at the end. */
265
266 /* Calculate day of year from year, month, and day of month.
267 The result need not be in range. */
268 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
269 [mon_remainder + 12 * negative_mon_remainder])
270 + mday - 1);
271
89752145 272 int sec_requested = sec;
98f1928d
PE
273#if LEAP_SECONDS_POSSIBLE
274 /* Handle out-of-range seconds specially,
275 since ydhms_tm_diff assumes every minute has 60 seconds. */
98f1928d
PE
276 if (sec < 0)
277 sec = 0;
278 if (59 < sec)
279 sec = 59;
280#endif
281
282 /* Invert CONVERT by probing. First assume the same offset as last time.
283 Then repeatedly use the error to improve the guess. */
284
285 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
286 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
287 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
288
68c45bf0 289 for (t = t1 = t2 = t0 + *offset;
649e97a3
UD
290 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
291 ranged_convert (convert, &t, &tm)));
68c45bf0
PE
292 t1 = t2, t2 = t, t += dt)
293 if (t == t1 && t != t2
294 && (isdst < 0 || tm.tm_isdst < 0
295 || (isdst != 0) != (tm.tm_isdst != 0)))
296 /* We can't possibly find a match, as we are oscillating
297 between two values. The requested time probably falls
298 within a spring-forward gap of size DT. Follow the common
299 practice in this case, which is to return a time that is DT
300 away from the requested time, preferring a time whose
301 tm_isdst differs from the requested value. In practice,
302 this is more useful than returning -1. */
303 break;
304 else if (--remaining_probes == 0)
98f1928d
PE
305 return -1;
306
68c45bf0
PE
307 /* If we have a match, check whether tm.tm_isdst has the requested
308 value, if any. */
309 if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
98f1928d 310 {
68c45bf0
PE
311 /* tm.tm_isdst has the wrong value. Look for a neighboring
312 time with the right value, and use its UTC offset.
313 Heuristic: probe the previous three calendar quarters (approximately),
314 looking for the desired isdst. This isn't perfect,
315 but it's good enough in practice. */
316 int quarter = 7889238; /* seconds per average 1/4 Gregorian year */
317 int i;
318
319 /* If we're too close to the time_t limit, look in future quarters. */
320 if (t < TIME_T_MIN + 3 * quarter)
321 quarter = -quarter;
322
323 for (i = 1; i <= 3; i++)
98f1928d 324 {
68c45bf0
PE
325 time_t ot = t - i * quarter;
326 struct tm otm;
327 ranged_convert (convert, &ot, &otm);
328 if (otm.tm_isdst == isdst)
98f1928d 329 {
68c45bf0
PE
330 /* We found the desired tm_isdst.
331 Extrapolate back to the desired time. */
332 t = ot + ydhms_tm_diff (year, yday, hour, min, sec, &otm);
333 ranged_convert (convert, &t, &tm);
334 break;
98f1928d
PE
335 }
336 }
337 }
338
339 *offset = t - t0;
340
341#if LEAP_SECONDS_POSSIBLE
342 if (sec_requested != tm.tm_sec)
343 {
344 /* Adjust time to reflect the tm_sec requested, not the normalized value.
345 Also, repair any damage from a false match due to a leap second. */
346 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
649e97a3
UD
347 if (! (*convert) (&t, &tm))
348 return -1;
98f1928d
PE
349 }
350#endif
351
352 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
353 {
354 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
355 so check for major overflows. A gross check suffices,
356 since if t has overflowed, it is off by a multiple of
357 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
358 the difference that is bounded by a small value. */
359
360 double dyear = (double) year_requested + mon_years - tm.tm_year;
361 double dday = 366 * dyear + mday;
362 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
363
067cc4dc
UD
364 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
365 correct results, ie., it erroneously gives a positive value
366 of 715827882. Setting a variable first then doing math on it
367 seems to work. (ghazi@caip.rutgers.edu) */
368
369 const time_t time_t_max = TIME_T_MAX;
370 const time_t time_t_min = TIME_T_MIN;
371
372 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
98f1928d
PE
373 return -1;
374 }
375
376 *tp = tm;
377 return t;
378}
379
68c45bf0
PE
380
381static time_t localtime_offset;
382
383/* Convert *TP to a time_t value. */
384time_t
385mktime (tp)
386 struct tm *tp;
387{
388#ifdef _LIBC
389 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
390 time zone names contained in the external variable `tzname' shall
391 be set as if the tzset() function had been called. */
392 __tzset ();
393#endif
394
395 return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
396}
397
98f1928d
PE
398#ifdef weak_alias
399weak_alias (mktime, timelocal)
400#endif
401\f
402#if DEBUG
403
404static int
405not_equal_tm (a, b)
406 struct tm *a;
407 struct tm *b;
408{
409 return ((a->tm_sec ^ b->tm_sec)
410 | (a->tm_min ^ b->tm_min)
411 | (a->tm_hour ^ b->tm_hour)
412 | (a->tm_mday ^ b->tm_mday)
413 | (a->tm_mon ^ b->tm_mon)
414 | (a->tm_year ^ b->tm_year)
415 | (a->tm_mday ^ b->tm_mday)
416 | (a->tm_yday ^ b->tm_yday)
417 | (a->tm_isdst ^ b->tm_isdst));
418}
419
420static void
421print_tm (tp)
422 struct tm *tp;
423{
649e97a3
UD
424 if (tp)
425 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
426 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
427 tp->tm_hour, tp->tm_min, tp->tm_sec,
428 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
429 else
430 printf ("0");
98f1928d
PE
431}
432
433static int
649e97a3 434check_result (tk, tmk, tl, lt)
98f1928d
PE
435 time_t tk;
436 struct tm tmk;
437 time_t tl;
649e97a3 438 struct tm *lt;
98f1928d 439{
649e97a3 440 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
98f1928d
PE
441 {
442 printf ("mktime (");
443 print_tm (&tmk);
444 printf (")\nyields (");
649e97a3 445 print_tm (lt);
98f1928d
PE
446 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
447 return 1;
448 }
449
450 return 0;
451}
452
453int
454main (argc, argv)
455 int argc;
456 char **argv;
457{
458 int status = 0;
459 struct tm tm, tmk, tml;
649e97a3 460 struct tm *lt;
98f1928d
PE
461 time_t tk, tl;
462 char trailer;
463
464 if ((argc == 3 || argc == 4)
465 && (sscanf (argv[1], "%d-%d-%d%c",
466 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
467 == 3)
468 && (sscanf (argv[2], "%d:%d:%d%c",
469 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
470 == 3))
471 {
472 tm.tm_year -= TM_YEAR_BASE;
473 tm.tm_mon--;
474 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
475 tmk = tm;
476 tl = mktime (&tmk);
649e97a3
UD
477 lt = localtime (&tl);
478 if (lt)
479 {
480 tml = *lt;
481 lt = &tml;
482 }
98f1928d
PE
483 printf ("mktime returns %ld == ", (long) tl);
484 print_tm (&tmk);
485 printf ("\n");
649e97a3 486 status = check_result (tl, tmk, tl, lt);
98f1928d
PE
487 }
488 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
489 {
490 time_t from = atol (argv[1]);
491 time_t by = atol (argv[2]);
492 time_t to = atol (argv[3]);
493
494 if (argc == 4)
495 for (tl = from; tl <= to; tl += by)
496 {
649e97a3
UD
497 lt = localtime (&tl);
498 if (lt)
499 {
500 tmk = tml = *lt;
501 tk = mktime (&tmk);
502 status |= check_result (tk, tmk, tl, tml);
503 }
504 else
505 {
506 printf ("localtime (%ld) yields 0\n", (long) tl);
507 status = 1;
508 }
98f1928d
PE
509 }
510 else
511 for (tl = from; tl <= to; tl += by)
512 {
513 /* Null benchmark. */
649e97a3
UD
514 lt = localtime (&tl);
515 if (lt)
516 {
517 tmk = tml = *lt;
518 tk = tl;
519 status |= check_result (tk, tmk, tl, tml);
520 }
521 else
522 {
523 printf ("localtime (%ld) yields 0\n", (long) tl);
524 status = 1;
525 }
98f1928d
PE
526 }
527 }
528 else
529 printf ("Usage:\
530\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
531\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
532\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
533 argv[0], argv[0], argv[0]);
534
535 return status;
536}
537
538#endif /* DEBUG */
539\f
540/*
541Local Variables:
68c45bf0 542compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
98f1928d
PE
543End:
544*/