Revision: miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-483
[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
984257db
DL
255 /* 1 if the previous probe was DST. */
256 int dst2;
257
98f1928d
PE
258 /* Ensure that mon is in range, and set year accordingly. */
259 int mon_remainder = mon % 12;
260 int negative_mon_remainder = mon_remainder < 0;
261 int mon_years = mon / 12 - negative_mon_remainder;
262 int year = year_requested + mon_years;
263
264 /* The other values need not be in range:
265 the remaining code handles minor overflows correctly,
266 assuming int and time_t arithmetic wraps around.
267 Major overflows are caught at the end. */
268
269 /* Calculate day of year from year, month, and day of month.
270 The result need not be in range. */
271 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
272 [mon_remainder + 12 * negative_mon_remainder])
273 + mday - 1);
274
89752145 275 int sec_requested = sec;
984257db
DL
276
277 /* Only years after 1970 are defined.
278 If year is 69, it might still be representable due to
279 timezone differences. */
280 if (year < 69)
281 return -1;
282
98f1928d
PE
283#if LEAP_SECONDS_POSSIBLE
284 /* Handle out-of-range seconds specially,
285 since ydhms_tm_diff assumes every minute has 60 seconds. */
98f1928d
PE
286 if (sec < 0)
287 sec = 0;
288 if (59 < sec)
289 sec = 59;
290#endif
291
292 /* Invert CONVERT by probing. First assume the same offset as last time.
293 Then repeatedly use the error to improve the guess. */
294
295 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
296 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
297 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
298
984257db 299 for (t = t1 = t2 = t0 + *offset, dst2 = 0;
649e97a3
UD
300 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
301 ranged_convert (convert, &t, &tm)));
984257db 302 t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0)
68c45bf0 303 if (t == t1 && t != t2
984257db
DL
304 && (tm.tm_isdst < 0
305 || (isdst < 0
306 ? dst2 <= (tm.tm_isdst != 0)
307 : (isdst != 0) != (tm.tm_isdst != 0))))
68c45bf0
PE
308 /* We can't possibly find a match, as we are oscillating
309 between two values. The requested time probably falls
310 within a spring-forward gap of size DT. Follow the common
311 practice in this case, which is to return a time that is DT
312 away from the requested time, preferring a time whose
984257db
DL
313 tm_isdst differs from the requested value. (If no tm_isdst
314 was requested and only one of the two values has a nonzero
315 tm_isdst, prefer that value.) In practice, this is more
316 useful than returning -1. */
68c45bf0
PE
317 break;
318 else if (--remaining_probes == 0)
98f1928d
PE
319 return -1;
320
68c45bf0
PE
321 /* If we have a match, check whether tm.tm_isdst has the requested
322 value, if any. */
323 if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
98f1928d 324 {
68c45bf0
PE
325 /* tm.tm_isdst has the wrong value. Look for a neighboring
326 time with the right value, and use its UTC offset.
327 Heuristic: probe the previous three calendar quarters (approximately),
328 looking for the desired isdst. This isn't perfect,
329 but it's good enough in practice. */
330 int quarter = 7889238; /* seconds per average 1/4 Gregorian year */
331 int i;
332
333 /* If we're too close to the time_t limit, look in future quarters. */
334 if (t < TIME_T_MIN + 3 * quarter)
335 quarter = -quarter;
336
337 for (i = 1; i <= 3; i++)
98f1928d 338 {
68c45bf0
PE
339 time_t ot = t - i * quarter;
340 struct tm otm;
341 ranged_convert (convert, &ot, &otm);
342 if (otm.tm_isdst == isdst)
98f1928d 343 {
68c45bf0
PE
344 /* We found the desired tm_isdst.
345 Extrapolate back to the desired time. */
346 t = ot + ydhms_tm_diff (year, yday, hour, min, sec, &otm);
347 ranged_convert (convert, &t, &tm);
348 break;
98f1928d
PE
349 }
350 }
351 }
352
353 *offset = t - t0;
354
355#if LEAP_SECONDS_POSSIBLE
356 if (sec_requested != tm.tm_sec)
357 {
358 /* Adjust time to reflect the tm_sec requested, not the normalized value.
359 Also, repair any damage from a false match due to a leap second. */
360 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
649e97a3
UD
361 if (! (*convert) (&t, &tm))
362 return -1;
98f1928d
PE
363 }
364#endif
365
366 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
367 {
368 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
369 so check for major overflows. A gross check suffices,
370 since if t has overflowed, it is off by a multiple of
371 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
372 the difference that is bounded by a small value. */
373
374 double dyear = (double) year_requested + mon_years - tm.tm_year;
375 double dday = 366 * dyear + mday;
376 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
377
067cc4dc
UD
378 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
379 correct results, ie., it erroneously gives a positive value
380 of 715827882. Setting a variable first then doing math on it
381 seems to work. (ghazi@caip.rutgers.edu) */
382
383 const time_t time_t_max = TIME_T_MAX;
384 const time_t time_t_min = TIME_T_MIN;
385
386 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
98f1928d
PE
387 return -1;
388 }
389
984257db
DL
390 if (year == 69)
391 {
392 /* If year was 69, need to check whether the time was representable
393 or not. */
394 if (t < 0 || t > 2 * 24 * 60 * 60)
395 return -1;
396 }
397
98f1928d
PE
398 *tp = tm;
399 return t;
400}
401
68c45bf0
PE
402
403static time_t localtime_offset;
404
405/* Convert *TP to a time_t value. */
406time_t
407mktime (tp)
408 struct tm *tp;
409{
410#ifdef _LIBC
411 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
412 time zone names contained in the external variable `tzname' shall
413 be set as if the tzset() function had been called. */
414 __tzset ();
415#endif
416
417 return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
418}
419
98f1928d
PE
420#ifdef weak_alias
421weak_alias (mktime, timelocal)
422#endif
423\f
424#if DEBUG
425
426static int
427not_equal_tm (a, b)
428 struct tm *a;
429 struct tm *b;
430{
431 return ((a->tm_sec ^ b->tm_sec)
432 | (a->tm_min ^ b->tm_min)
433 | (a->tm_hour ^ b->tm_hour)
434 | (a->tm_mday ^ b->tm_mday)
435 | (a->tm_mon ^ b->tm_mon)
436 | (a->tm_year ^ b->tm_year)
437 | (a->tm_mday ^ b->tm_mday)
438 | (a->tm_yday ^ b->tm_yday)
439 | (a->tm_isdst ^ b->tm_isdst));
440}
441
442static void
443print_tm (tp)
444 struct tm *tp;
445{
649e97a3
UD
446 if (tp)
447 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
448 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
449 tp->tm_hour, tp->tm_min, tp->tm_sec,
450 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
451 else
452 printf ("0");
98f1928d
PE
453}
454
455static int
649e97a3 456check_result (tk, tmk, tl, lt)
98f1928d
PE
457 time_t tk;
458 struct tm tmk;
459 time_t tl;
649e97a3 460 struct tm *lt;
98f1928d 461{
649e97a3 462 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
98f1928d
PE
463 {
464 printf ("mktime (");
465 print_tm (&tmk);
466 printf (")\nyields (");
649e97a3 467 print_tm (lt);
98f1928d
PE
468 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
469 return 1;
470 }
471
472 return 0;
473}
474
475int
476main (argc, argv)
477 int argc;
478 char **argv;
479{
480 int status = 0;
481 struct tm tm, tmk, tml;
649e97a3 482 struct tm *lt;
98f1928d
PE
483 time_t tk, tl;
484 char trailer;
485
486 if ((argc == 3 || argc == 4)
487 && (sscanf (argv[1], "%d-%d-%d%c",
488 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
489 == 3)
490 && (sscanf (argv[2], "%d:%d:%d%c",
491 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
492 == 3))
493 {
494 tm.tm_year -= TM_YEAR_BASE;
495 tm.tm_mon--;
496 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
497 tmk = tm;
498 tl = mktime (&tmk);
649e97a3
UD
499 lt = localtime (&tl);
500 if (lt)
501 {
502 tml = *lt;
503 lt = &tml;
504 }
98f1928d
PE
505 printf ("mktime returns %ld == ", (long) tl);
506 print_tm (&tmk);
507 printf ("\n");
649e97a3 508 status = check_result (tl, tmk, tl, lt);
98f1928d
PE
509 }
510 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
511 {
512 time_t from = atol (argv[1]);
513 time_t by = atol (argv[2]);
514 time_t to = atol (argv[3]);
515
516 if (argc == 4)
517 for (tl = from; tl <= to; tl += by)
518 {
649e97a3
UD
519 lt = localtime (&tl);
520 if (lt)
521 {
522 tmk = tml = *lt;
523 tk = mktime (&tmk);
524 status |= check_result (tk, tmk, tl, tml);
525 }
526 else
527 {
528 printf ("localtime (%ld) yields 0\n", (long) tl);
529 status = 1;
530 }
98f1928d
PE
531 }
532 else
533 for (tl = from; tl <= to; tl += by)
534 {
535 /* Null benchmark. */
649e97a3
UD
536 lt = localtime (&tl);
537 if (lt)
538 {
539 tmk = tml = *lt;
540 tk = tl;
541 status |= check_result (tk, tmk, tl, tml);
542 }
543 else
544 {
545 printf ("localtime (%ld) yields 0\n", (long) tl);
546 status = 1;
547 }
98f1928d
PE
548 }
549 }
550 else
551 printf ("Usage:\
552\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
553\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
554\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
555 argv[0], argv[0], argv[0]);
556
557 return status;
558}
559
560#endif /* DEBUG */
561\f
562/*
563Local Variables:
68c45bf0 564compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
98f1928d
PE
565End:
566*/
ab5796a9
MB
567
568/* arch-tag: 9456752f-7ddd-47cb-8286-fa807b1355ae
569 (do not change this comment) */