Add support for large files, 64-bit Solaris, system locale codings.
[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 *
68c45bf0 120my_mktime_localtime_r (const time_t *t, struct tm *tp)
98f1928d
PE
121{
122 struct tm *l = localtime (t);
123 if (! l)
124 return 0;
125 *tp = *l;
126 return tp;
127}
98f1928d
PE
128#endif /* ! _LIBC */
129
130
131/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
132 measured in seconds, ignoring leap seconds.
133 YEAR uses the same numbering as TM->tm_year.
134 All values are in range, except possibly YEAR.
649e97a3 135 If TP is null, return a nonzero value.
98f1928d
PE
136 If overflow occurs, yield the low order bits of the correct answer. */
137static time_t
68c45bf0
PE
138ydhms_tm_diff (int year, int yday, int hour, int min, int sec,
139 const struct tm *tp)
98f1928d 140{
649e97a3
UD
141 if (!tp)
142 return 1;
143 else
144 {
145 /* Compute intervening leap days correctly even if year is negative.
146 Take care to avoid int overflow. time_t overflow is OK, since
147 only the low order bits of the correct time_t answer are needed.
148 Don't convert to time_t until after all divisions are done, since
149 time_t might be unsigned. */
150 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
151 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
152 int a100 = a4 / 25 - (a4 % 25 < 0);
153 int b100 = b4 / 25 - (b4 % 25 < 0);
154 int a400 = a100 >> 2;
155 int b400 = b100 >> 2;
156 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
157 time_t years = year - (time_t) tp->tm_year;
158 time_t days = (365 * years + intervening_leap_days
159 + (yday - tp->tm_yday));
160 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
161 + (min - tp->tm_min))
162 + (sec - tp->tm_sec));
163 }
98f1928d
PE
164}
165
649e97a3
UD
166/* Use CONVERT to convert *T to a broken down time in *TP.
167 If *T is out of range for conversion, adjust it so that
168 it is the nearest in-range value and then convert that. */
169static struct tm *
68c45bf0
PE
170ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
171 time_t *t, struct tm *tp)
649e97a3
UD
172{
173 struct tm *r;
174
175 if (! (r = (*convert) (t, tp)) && *t)
176 {
177 time_t bad = *t;
178 time_t ok = 0;
179 struct tm tm;
180
181 /* BAD is a known unconvertible time_t, and OK is a known good one.
182 Use binary search to narrow the range between BAD and OK until
183 they differ by 1. */
184 while (bad != ok + (bad < 0 ? -1 : 1))
185 {
186 time_t mid = *t = (bad < 0
187 ? bad + ((ok - bad) >> 1)
188 : ok + ((bad - ok) >> 1));
189 if ((r = (*convert) (t, tp)))
190 {
191 tm = *r;
192 ok = mid;
193 }
194 else
195 bad = mid;
196 }
197
198 if (!r && ok)
199 {
200 /* The last conversion attempt failed;
201 revert to the most recent successful attempt. */
202 *t = ok;
203 *tp = tm;
204 r = tp;
205 }
206 }
207
208 return r;
209}
210
211
98f1928d
PE
212/* Convert *TP to a time_t value, inverting
213 the monotonic and mostly-unit-linear conversion function CONVERT.
214 Use *OFFSET to keep track of a guess at the offset of the result,
215 compared to what the result would be for UTC without leap seconds.
216 If *OFFSET's guess is correct, only one CONVERT call is needed. */
217time_t
68c45bf0
PE
218__mktime_internal (struct tm *tp,
219 struct tm *(*convert) (const time_t *, struct tm *),
220 time_t *offset)
98f1928d 221{
68c45bf0 222 time_t t, dt, t0, t1, t2;
98f1928d
PE
223 struct tm tm;
224
225 /* The maximum number of probes (calls to CONVERT) should be enough
226 to handle any combinations of time zone rule changes, solar time,
68c45bf0
PE
227 leap seconds, and oscillations around a spring-forward gap.
228 POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
229 int remaining_probes = 6;
98f1928d
PE
230
231 /* Time requested. Copy it in case CONVERT modifies *TP; this can
232 occur if TP is localtime's returned value and CONVERT is localtime. */
233 int sec = tp->tm_sec;
234 int min = tp->tm_min;
235 int hour = tp->tm_hour;
236 int mday = tp->tm_mday;
237 int mon = tp->tm_mon;
238 int year_requested = tp->tm_year;
239 int isdst = tp->tm_isdst;
240
241 /* Ensure that mon is in range, and set year accordingly. */
242 int mon_remainder = mon % 12;
243 int negative_mon_remainder = mon_remainder < 0;
244 int mon_years = mon / 12 - negative_mon_remainder;
245 int year = year_requested + mon_years;
246
247 /* The other values need not be in range:
248 the remaining code handles minor overflows correctly,
249 assuming int and time_t arithmetic wraps around.
250 Major overflows are caught at the end. */
251
252 /* Calculate day of year from year, month, and day of month.
253 The result need not be in range. */
254 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
255 [mon_remainder + 12 * negative_mon_remainder])
256 + mday - 1);
257
89752145 258 int sec_requested = sec;
98f1928d
PE
259#if LEAP_SECONDS_POSSIBLE
260 /* Handle out-of-range seconds specially,
261 since ydhms_tm_diff assumes every minute has 60 seconds. */
98f1928d
PE
262 if (sec < 0)
263 sec = 0;
264 if (59 < sec)
265 sec = 59;
266#endif
267
268 /* Invert CONVERT by probing. First assume the same offset as last time.
269 Then repeatedly use the error to improve the guess. */
270
271 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
272 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
273 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
274
68c45bf0 275 for (t = t1 = t2 = t0 + *offset;
649e97a3
UD
276 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
277 ranged_convert (convert, &t, &tm)));
68c45bf0
PE
278 t1 = t2, t2 = t, t += dt)
279 if (t == t1 && t != t2
280 && (isdst < 0 || tm.tm_isdst < 0
281 || (isdst != 0) != (tm.tm_isdst != 0)))
282 /* We can't possibly find a match, as we are oscillating
283 between two values. The requested time probably falls
284 within a spring-forward gap of size DT. Follow the common
285 practice in this case, which is to return a time that is DT
286 away from the requested time, preferring a time whose
287 tm_isdst differs from the requested value. In practice,
288 this is more useful than returning -1. */
289 break;
290 else if (--remaining_probes == 0)
98f1928d
PE
291 return -1;
292
68c45bf0
PE
293 /* If we have a match, check whether tm.tm_isdst has the requested
294 value, if any. */
295 if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
98f1928d 296 {
68c45bf0
PE
297 /* tm.tm_isdst has the wrong value. Look for a neighboring
298 time with the right value, and use its UTC offset.
299 Heuristic: probe the previous three calendar quarters (approximately),
300 looking for the desired isdst. This isn't perfect,
301 but it's good enough in practice. */
302 int quarter = 7889238; /* seconds per average 1/4 Gregorian year */
303 int i;
304
305 /* If we're too close to the time_t limit, look in future quarters. */
306 if (t < TIME_T_MIN + 3 * quarter)
307 quarter = -quarter;
308
309 for (i = 1; i <= 3; i++)
98f1928d 310 {
68c45bf0
PE
311 time_t ot = t - i * quarter;
312 struct tm otm;
313 ranged_convert (convert, &ot, &otm);
314 if (otm.tm_isdst == isdst)
98f1928d 315 {
68c45bf0
PE
316 /* We found the desired tm_isdst.
317 Extrapolate back to the desired time. */
318 t = ot + ydhms_tm_diff (year, yday, hour, min, sec, &otm);
319 ranged_convert (convert, &t, &tm);
320 break;
98f1928d
PE
321 }
322 }
323 }
324
325 *offset = t - t0;
326
327#if LEAP_SECONDS_POSSIBLE
328 if (sec_requested != tm.tm_sec)
329 {
330 /* Adjust time to reflect the tm_sec requested, not the normalized value.
331 Also, repair any damage from a false match due to a leap second. */
332 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
649e97a3
UD
333 if (! (*convert) (&t, &tm))
334 return -1;
98f1928d
PE
335 }
336#endif
337
338 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
339 {
340 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
341 so check for major overflows. A gross check suffices,
342 since if t has overflowed, it is off by a multiple of
343 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
344 the difference that is bounded by a small value. */
345
346 double dyear = (double) year_requested + mon_years - tm.tm_year;
347 double dday = 366 * dyear + mday;
348 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
349
067cc4dc
UD
350 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
351 correct results, ie., it erroneously gives a positive value
352 of 715827882. Setting a variable first then doing math on it
353 seems to work. (ghazi@caip.rutgers.edu) */
354
355 const time_t time_t_max = TIME_T_MAX;
356 const time_t time_t_min = TIME_T_MIN;
357
358 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
98f1928d
PE
359 return -1;
360 }
361
362 *tp = tm;
363 return t;
364}
365
68c45bf0
PE
366
367static time_t localtime_offset;
368
369/* Convert *TP to a time_t value. */
370time_t
371mktime (tp)
372 struct tm *tp;
373{
374#ifdef _LIBC
375 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
376 time zone names contained in the external variable `tzname' shall
377 be set as if the tzset() function had been called. */
378 __tzset ();
379#endif
380
381 return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
382}
383
98f1928d
PE
384#ifdef weak_alias
385weak_alias (mktime, timelocal)
386#endif
387\f
388#if DEBUG
389
390static int
391not_equal_tm (a, b)
392 struct tm *a;
393 struct tm *b;
394{
395 return ((a->tm_sec ^ b->tm_sec)
396 | (a->tm_min ^ b->tm_min)
397 | (a->tm_hour ^ b->tm_hour)
398 | (a->tm_mday ^ b->tm_mday)
399 | (a->tm_mon ^ b->tm_mon)
400 | (a->tm_year ^ b->tm_year)
401 | (a->tm_mday ^ b->tm_mday)
402 | (a->tm_yday ^ b->tm_yday)
403 | (a->tm_isdst ^ b->tm_isdst));
404}
405
406static void
407print_tm (tp)
408 struct tm *tp;
409{
649e97a3
UD
410 if (tp)
411 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
412 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
413 tp->tm_hour, tp->tm_min, tp->tm_sec,
414 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
415 else
416 printf ("0");
98f1928d
PE
417}
418
419static int
649e97a3 420check_result (tk, tmk, tl, lt)
98f1928d
PE
421 time_t tk;
422 struct tm tmk;
423 time_t tl;
649e97a3 424 struct tm *lt;
98f1928d 425{
649e97a3 426 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
98f1928d
PE
427 {
428 printf ("mktime (");
429 print_tm (&tmk);
430 printf (")\nyields (");
649e97a3 431 print_tm (lt);
98f1928d
PE
432 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
433 return 1;
434 }
435
436 return 0;
437}
438
439int
440main (argc, argv)
441 int argc;
442 char **argv;
443{
444 int status = 0;
445 struct tm tm, tmk, tml;
649e97a3 446 struct tm *lt;
98f1928d
PE
447 time_t tk, tl;
448 char trailer;
449
450 if ((argc == 3 || argc == 4)
451 && (sscanf (argv[1], "%d-%d-%d%c",
452 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
453 == 3)
454 && (sscanf (argv[2], "%d:%d:%d%c",
455 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
456 == 3))
457 {
458 tm.tm_year -= TM_YEAR_BASE;
459 tm.tm_mon--;
460 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
461 tmk = tm;
462 tl = mktime (&tmk);
649e97a3
UD
463 lt = localtime (&tl);
464 if (lt)
465 {
466 tml = *lt;
467 lt = &tml;
468 }
98f1928d
PE
469 printf ("mktime returns %ld == ", (long) tl);
470 print_tm (&tmk);
471 printf ("\n");
649e97a3 472 status = check_result (tl, tmk, tl, lt);
98f1928d
PE
473 }
474 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
475 {
476 time_t from = atol (argv[1]);
477 time_t by = atol (argv[2]);
478 time_t to = atol (argv[3]);
479
480 if (argc == 4)
481 for (tl = from; tl <= to; tl += by)
482 {
649e97a3
UD
483 lt = localtime (&tl);
484 if (lt)
485 {
486 tmk = tml = *lt;
487 tk = mktime (&tmk);
488 status |= check_result (tk, tmk, tl, tml);
489 }
490 else
491 {
492 printf ("localtime (%ld) yields 0\n", (long) tl);
493 status = 1;
494 }
98f1928d
PE
495 }
496 else
497 for (tl = from; tl <= to; tl += by)
498 {
499 /* Null benchmark. */
649e97a3
UD
500 lt = localtime (&tl);
501 if (lt)
502 {
503 tmk = tml = *lt;
504 tk = tl;
505 status |= check_result (tk, tmk, tl, tml);
506 }
507 else
508 {
509 printf ("localtime (%ld) yields 0\n", (long) tl);
510 status = 1;
511 }
98f1928d
PE
512 }
513 }
514 else
515 printf ("Usage:\
516\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
517\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
518\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
519 argv[0], argv[0], argv[0]);
520
521 return status;
522}
523
524#endif /* DEBUG */
525\f
526/*
527Local Variables:
68c45bf0 528compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
98f1928d
PE
529End:
530*/