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