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