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