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