announce-gen: use Digest::SHA when possible
[gnulib.git] / lib / mktime.c
1 /* Convert a 'struct tm' to a time_t value.
2    Copyright (C) 1993-1999, 2002-2007, 2009-2012 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Paul Eggert <eggert@twinsun.com>.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, see <http://www.gnu.org/licenses/>.  */
18
19 /* Define this to have a standalone program to test this implementation of
20    mktime.  */
21 /* #define DEBUG 1 */
22
23 #ifndef _LIBC
24 # include <config.h>
25 #endif
26
27 /* Assume that leap seconds are possible, unless told otherwise.
28    If the host has a 'zic' command with a '-L leapsecondfilename' option,
29    then it supports leap seconds; otherwise it probably doesn't.  */
30 #ifndef LEAP_SECONDS_POSSIBLE
31 # define LEAP_SECONDS_POSSIBLE 1
32 #endif
33
34 #include <time.h>
35
36 #include <limits.h>
37
38 #include <string.h>             /* For the real memcpy prototype.  */
39
40 #if DEBUG
41 # include <stdio.h>
42 # include <stdlib.h>
43 /* Make it work even if the system's libc has its own mktime routine.  */
44 # undef mktime
45 # define mktime my_mktime
46 #endif /* DEBUG */
47
48 /* Some of the code in this file assumes that signed integer overflow
49    silently wraps around.  This assumption can't easily be programmed
50    around, nor can it be checked for portably at compile-time or
51    easily eliminated at run-time.
52
53    Define WRAPV to 1 if the assumption is valid and if
54      #pragma GCC optimize ("wrapv")
55    does not trigger GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51793>.
56    Otherwise, define it to 0; this forces the use of slower code that,
57    while not guaranteed by the C Standard, works on all production
58    platforms that we know about.  */
59 #ifndef WRAPV
60 # if ((__GNUC__ == 4 && 4 <= __GNUC_MINOR__) || 4 < __GNUC__) && defined __GLIBC__
61 #  pragma GCC optimize ("wrapv")
62 #  define WRAPV 1
63 # else
64 #  define WRAPV 0
65 # endif
66 #endif
67
68 /* Verify a requirement at compile-time (unlike assert, which is runtime).  */
69 #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
70
71 /* A signed type that is at least one bit wider than int.  */
72 #if INT_MAX <= LONG_MAX / 2
73 typedef long int long_int;
74 #else
75 typedef long long int long_int;
76 #endif
77 verify (long_int_is_wide_enough, INT_MAX == INT_MAX * (long_int) 2 / 2);
78
79 /* Shift A right by B bits portably, by dividing A by 2**B and
80    truncating towards minus infinity.  A and B should be free of side
81    effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
82    INT_BITS is the number of useful bits in an int.  GNU code can
83    assume that INT_BITS is at least 32.
84
85    ISO C99 says that A >> B is implementation-defined if A < 0.  Some
86    implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
87    right in the usual way when A < 0, so SHR falls back on division if
88    ordinary A >> B doesn't seem to be the usual signed shift.  */
89 #define SHR(a, b)                                               \
90   ((-1 >> 1 == -1                                               \
91     && (long_int) -1 >> 1 == -1                                 \
92     && ((time_t) -1 >> 1 == -1 || ! TYPE_SIGNED (time_t)))      \
93    ? (a) >> (b)                                                 \
94    : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
95
96 /* The extra casts in the following macros work around compiler bugs,
97    e.g., in Cray C 5.0.3.0.  */
98
99 /* True if the arithmetic type T is an integer type.  bool counts as
100    an integer.  */
101 #define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)
102
103 /* True if negative values of the signed integer type T use two's
104    complement, or if T is an unsigned integer type.  */
105 #define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
106
107 /* True if the arithmetic type T is signed.  */
108 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
109
110 /* The maximum and minimum values for the integer type T.  These
111    macros have undefined behavior if T is signed and has padding bits.
112    If this is a problem for you, please let us know how to fix it for
113    your host.  */
114 #define TYPE_MINIMUM(t) \
115   ((t) (! TYPE_SIGNED (t) \
116         ? (t) 0 \
117         : ~ TYPE_MAXIMUM (t)))
118 #define TYPE_MAXIMUM(t) \
119   ((t) (! TYPE_SIGNED (t) \
120         ? (t) -1 \
121         : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
122
123 #ifndef TIME_T_MIN
124 # define TIME_T_MIN TYPE_MINIMUM (time_t)
125 #endif
126 #ifndef TIME_T_MAX
127 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
128 #endif
129 #define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
130
131 verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
132 verify (twos_complement_arithmetic,
133         (TYPE_TWOS_COMPLEMENT (int)
134          && TYPE_TWOS_COMPLEMENT (long_int)
135          && TYPE_TWOS_COMPLEMENT (time_t)));
136
137 #define EPOCH_YEAR 1970
138 #define TM_YEAR_BASE 1900
139 verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
140
141 /* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
142 static inline int
143 leapyear (long_int year)
144 {
145   /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
146      Also, work even if YEAR is negative.  */
147   return
148     ((year & 3) == 0
149      && (year % 100 != 0
150          || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
151 }
152
153 /* How many days come before each month (0-12).  */
154 #ifndef _LIBC
155 static
156 #endif
157 const unsigned short int __mon_yday[2][13] =
158   {
159     /* Normal years.  */
160     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
161     /* Leap years.  */
162     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
163   };
164
165
166 #ifndef _LIBC
167 /* Portable standalone applications should supply a <time.h> that
168    declares a POSIX-compliant localtime_r, for the benefit of older
169    implementations that lack localtime_r or have a nonstandard one.
170    See the gnulib time_r module for one way to implement this.  */
171 # undef __localtime_r
172 # define __localtime_r localtime_r
173 # define __mktime_internal mktime_internal
174 # include "mktime-internal.h"
175 #endif
176
177 /* Return 1 if the values A and B differ according to the rules for
178    tm_isdst: A and B differ if one is zero and the other positive.  */
179 static int
180 isdst_differ (int a, int b)
181 {
182   return (!a != !b) & (0 <= a) & (0 <= b);
183 }
184
185 /* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
186    (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
187    were not adjusted between the time stamps.
188
189    The YEAR values uses the same numbering as TP->tm_year.  Values
190    need not be in the usual range.  However, YEAR1 must not be less
191    than 2 * INT_MIN or greater than 2 * INT_MAX.
192
193    The result may overflow.  It is the caller's responsibility to
194    detect overflow.  */
195
196 static inline time_t
197 ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
198             int year0, int yday0, int hour0, int min0, int sec0)
199 {
200   verify (C99_integer_division, -1 / 2 == 0);
201
202   /* Compute intervening leap days correctly even if year is negative.
203      Take care to avoid integer overflow here.  */
204   int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
205   int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
206   int a100 = a4 / 25 - (a4 % 25 < 0);
207   int b100 = b4 / 25 - (b4 % 25 < 0);
208   int a400 = SHR (a100, 2);
209   int b400 = SHR (b100, 2);
210   int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
211
212   /* Compute the desired time in time_t precision.  Overflow might
213      occur here.  */
214   time_t tyear1 = year1;
215   time_t years = tyear1 - year0;
216   time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
217   time_t hours = 24 * days + hour1 - hour0;
218   time_t minutes = 60 * hours + min1 - min0;
219   time_t seconds = 60 * minutes + sec1 - sec0;
220   return seconds;
221 }
222
223 /* Return the average of A and B, even if A + B would overflow.  */
224 static time_t
225 time_t_avg (time_t a, time_t b)
226 {
227   return SHR (a, 1) + SHR (b, 1) + (a & b & 1);
228 }
229
230 /* Return 1 if A + B does not overflow.  If time_t is unsigned and if
231    B's top bit is set, assume that the sum represents A - -B, and
232    return 1 if the subtraction does not wrap around.  */
233 static int
234 time_t_add_ok (time_t a, time_t b)
235 {
236   if (! TYPE_SIGNED (time_t))
237     {
238       time_t sum = a + b;
239       return (sum < a) == (TIME_T_MIDPOINT <= b);
240     }
241   else if (WRAPV)
242     {
243       time_t sum = a + b;
244       return (sum < a) == (b < 0);
245     }
246   else
247     {
248       time_t avg = time_t_avg (a, b);
249       return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
250     }
251 }
252
253 /* Return 1 if A + B does not overflow.  */
254 static int
255 time_t_int_add_ok (time_t a, int b)
256 {
257   verify (int_no_wider_than_time_t, INT_MAX <= TIME_T_MAX);
258   if (WRAPV)
259     {
260       time_t sum = a + b;
261       return (sum < a) == (b < 0);
262     }
263   else
264     {
265       int a_odd = a & 1;
266       time_t avg = SHR (a, 1) + (SHR (b, 1) + (a_odd & b));
267       return TIME_T_MIN / 2 <= avg && avg <= TIME_T_MAX / 2;
268     }
269 }
270
271 /* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
272    assuming that *T corresponds to *TP and that no clock adjustments
273    occurred between *TP and the desired time.
274    If TP is null, return a value not equal to *T; this avoids false matches.
275    If overflow occurs, yield the minimal or maximal value, except do not
276    yield a value equal to *T.  */
277 static time_t
278 guess_time_tm (long_int year, long_int yday, int hour, int min, int sec,
279                const time_t *t, const struct tm *tp)
280 {
281   if (tp)
282     {
283       time_t d = ydhms_diff (year, yday, hour, min, sec,
284                              tp->tm_year, tp->tm_yday,
285                              tp->tm_hour, tp->tm_min, tp->tm_sec);
286       if (time_t_add_ok (*t, d))
287         return *t + d;
288     }
289
290   /* Overflow occurred one way or another.  Return the nearest result
291      that is actually in range, except don't report a zero difference
292      if the actual difference is nonzero, as that would cause a false
293      match; and don't oscillate between two values, as that would
294      confuse the spring-forward gap detector.  */
295   return (*t < TIME_T_MIDPOINT
296           ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
297           : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
298 }
299
300 /* Use CONVERT to convert *T to a broken down time in *TP.
301    If *T is out of range for conversion, adjust it so that
302    it is the nearest in-range value and then convert that.  */
303 static struct tm *
304 ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
305                 time_t *t, struct tm *tp)
306 {
307   struct tm *r = convert (t, tp);
308
309   if (!r && *t)
310     {
311       time_t bad = *t;
312       time_t ok = 0;
313
314       /* BAD is a known unconvertible time_t, and OK is a known good one.
315          Use binary search to narrow the range between BAD and OK until
316          they differ by 1.  */
317       while (bad != ok + (bad < 0 ? -1 : 1))
318         {
319           time_t mid = *t = time_t_avg (ok, bad);
320           r = convert (t, tp);
321           if (r)
322             ok = mid;
323           else
324             bad = mid;
325         }
326
327       if (!r && ok)
328         {
329           /* The last conversion attempt failed;
330              revert to the most recent successful attempt.  */
331           *t = ok;
332           r = convert (t, tp);
333         }
334     }
335
336   return r;
337 }
338
339
340 /* Convert *TP to a time_t value, inverting
341    the monotonic and mostly-unit-linear conversion function CONVERT.
342    Use *OFFSET to keep track of a guess at the offset of the result,
343    compared to what the result would be for UTC without leap seconds.
344    If *OFFSET's guess is correct, only one CONVERT call is needed.
345    This function is external because it is used also by timegm.c.  */
346 time_t
347 __mktime_internal (struct tm *tp,
348                    struct tm *(*convert) (const time_t *, struct tm *),
349                    time_t *offset)
350 {
351   time_t t, gt, t0, t1, t2;
352   struct tm tm;
353
354   /* The maximum number of probes (calls to CONVERT) should be enough
355      to handle any combinations of time zone rule changes, solar time,
356      leap seconds, and oscillations around a spring-forward gap.
357      POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
358   int remaining_probes = 6;
359
360   /* Time requested.  Copy it in case CONVERT modifies *TP; this can
361      occur if TP is localtime's returned value and CONVERT is localtime.  */
362   int sec = tp->tm_sec;
363   int min = tp->tm_min;
364   int hour = tp->tm_hour;
365   int mday = tp->tm_mday;
366   int mon = tp->tm_mon;
367   int year_requested = tp->tm_year;
368   int isdst = tp->tm_isdst;
369
370   /* 1 if the previous probe was DST.  */
371   int dst2;
372
373   /* Ensure that mon is in range, and set year accordingly.  */
374   int mon_remainder = mon % 12;
375   int negative_mon_remainder = mon_remainder < 0;
376   int mon_years = mon / 12 - negative_mon_remainder;
377   long_int lyear_requested = year_requested;
378   long_int year = lyear_requested + mon_years;
379
380   /* The other values need not be in range:
381      the remaining code handles minor overflows correctly,
382      assuming int and time_t arithmetic wraps around.
383      Major overflows are caught at the end.  */
384
385   /* Calculate day of year from year, month, and day of month.
386      The result need not be in range.  */
387   int mon_yday = ((__mon_yday[leapyear (year)]
388                    [mon_remainder + 12 * negative_mon_remainder])
389                   - 1);
390   long_int lmday = mday;
391   long_int yday = mon_yday + lmday;
392
393   time_t guessed_offset = *offset;
394
395   int sec_requested = sec;
396
397   if (LEAP_SECONDS_POSSIBLE)
398     {
399       /* Handle out-of-range seconds specially,
400          since ydhms_tm_diff assumes every minute has 60 seconds.  */
401       if (sec < 0)
402         sec = 0;
403       if (59 < sec)
404         sec = 59;
405     }
406
407   /* Invert CONVERT by probing.  First assume the same offset as last
408      time.  */
409
410   t0 = ydhms_diff (year, yday, hour, min, sec,
411                    EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
412
413   if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
414     {
415       /* time_t isn't large enough to rule out overflows, so check
416          for major overflows.  A gross check suffices, since if t0
417          has overflowed, it is off by a multiple of TIME_T_MAX -
418          TIME_T_MIN + 1.  So ignore any component of the difference
419          that is bounded by a small value.  */
420
421       /* Approximate log base 2 of the number of time units per
422          biennium.  A biennium is 2 years; use this unit instead of
423          years to avoid integer overflow.  For example, 2 average
424          Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
425          which is 63113904 seconds, and rint (log2 (63113904)) is
426          26.  */
427       int ALOG2_SECONDS_PER_BIENNIUM = 26;
428       int ALOG2_MINUTES_PER_BIENNIUM = 20;
429       int ALOG2_HOURS_PER_BIENNIUM = 14;
430       int ALOG2_DAYS_PER_BIENNIUM = 10;
431       int LOG2_YEARS_PER_BIENNIUM = 1;
432
433       int approx_requested_biennia =
434         (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
435          - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
436          + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
437          + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
438          + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
439          + (LEAP_SECONDS_POSSIBLE
440             ? 0
441             : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
442
443       int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
444       int diff = approx_biennia - approx_requested_biennia;
445       int abs_diff = diff < 0 ? -1 - diff : diff;
446
447       /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
448          gives a positive value of 715827882.  Setting a variable
449          first then doing math on it seems to work.
450          (ghazi@caip.rutgers.edu) */
451       time_t time_t_max = TIME_T_MAX;
452       time_t time_t_min = TIME_T_MIN;
453       time_t overflow_threshold =
454         (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
455
456       if (overflow_threshold < abs_diff)
457         {
458           /* Overflow occurred.  Try repairing it; this might work if
459              the time zone offset is enough to undo the overflow.  */
460           time_t repaired_t0 = -1 - t0;
461           approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
462           diff = approx_biennia - approx_requested_biennia;
463           abs_diff = diff < 0 ? -1 - diff : diff;
464           if (overflow_threshold < abs_diff)
465             return -1;
466           guessed_offset += repaired_t0 - t0;
467           t0 = repaired_t0;
468         }
469     }
470
471   /* Repeatedly use the error to improve the guess.  */
472
473   for (t = t1 = t2 = t0, dst2 = 0;
474        (gt = guess_time_tm (year, yday, hour, min, sec, &t,
475                             ranged_convert (convert, &t, &tm)),
476         t != gt);
477        t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
478     if (t == t1 && t != t2
479         && (tm.tm_isdst < 0
480             || (isdst < 0
481                 ? dst2 <= (tm.tm_isdst != 0)
482                 : (isdst != 0) != (tm.tm_isdst != 0))))
483       /* We can't possibly find a match, as we are oscillating
484          between two values.  The requested time probably falls
485          within a spring-forward gap of size GT - T.  Follow the common
486          practice in this case, which is to return a time that is GT - T
487          away from the requested time, preferring a time whose
488          tm_isdst differs from the requested value.  (If no tm_isdst
489          was requested and only one of the two values has a nonzero
490          tm_isdst, prefer that value.)  In practice, this is more
491          useful than returning -1.  */
492       goto offset_found;
493     else if (--remaining_probes == 0)
494       return -1;
495
496   /* We have a match.  Check whether tm.tm_isdst has the requested
497      value, if any.  */
498   if (isdst_differ (isdst, tm.tm_isdst))
499     {
500       /* tm.tm_isdst has the wrong value.  Look for a neighboring
501          time with the right value, and use its UTC offset.
502
503          Heuristic: probe the adjacent timestamps in both directions,
504          looking for the desired isdst.  This should work for all real
505          time zone histories in the tz database.  */
506
507       /* Distance between probes when looking for a DST boundary.  In
508          tzdata2003a, the shortest period of DST is 601200 seconds
509          (e.g., America/Recife starting 2000-10-08 01:00), and the
510          shortest period of non-DST surrounded by DST is 694800
511          seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
512          minimum of these two values, so we don't miss these short
513          periods when probing.  */
514       int stride = 601200;
515
516       /* The longest period of DST in tzdata2003a is 536454000 seconds
517          (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
518          period of non-DST is much longer, but it makes no real sense
519          to search for more than a year of non-DST, so use the DST
520          max.  */
521       int duration_max = 536454000;
522
523       /* Search in both directions, so the maximum distance is half
524          the duration; add the stride to avoid off-by-1 problems.  */
525       int delta_bound = duration_max / 2 + stride;
526
527       int delta, direction;
528
529       for (delta = stride; delta < delta_bound; delta += stride)
530         for (direction = -1; direction <= 1; direction += 2)
531           if (time_t_int_add_ok (t, delta * direction))
532             {
533               time_t ot = t + delta * direction;
534               struct tm otm;
535               ranged_convert (convert, &ot, &otm);
536               if (! isdst_differ (isdst, otm.tm_isdst))
537                 {
538                   /* We found the desired tm_isdst.
539                      Extrapolate back to the desired time.  */
540                   t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
541                   ranged_convert (convert, &t, &tm);
542                   goto offset_found;
543                 }
544             }
545     }
546
547  offset_found:
548   *offset = guessed_offset + t - t0;
549
550   if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
551     {
552       /* Adjust time to reflect the tm_sec requested, not the normalized value.
553          Also, repair any damage from a false match due to a leap second.  */
554       int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
555       if (! time_t_int_add_ok (t, sec_requested))
556         return -1;
557       t1 = t + sec_requested;
558       if (! time_t_int_add_ok (t1, sec_adjustment))
559         return -1;
560       t2 = t1 + sec_adjustment;
561       if (! convert (&t2, &tm))
562         return -1;
563       t = t2;
564     }
565
566   *tp = tm;
567   return t;
568 }
569
570
571 /* FIXME: This should use a signed type wide enough to hold any UTC
572    offset in seconds.  'int' should be good enough for GNU code.  We
573    can't fix this unilaterally though, as other modules invoke
574    __mktime_internal.  */
575 static time_t localtime_offset;
576
577 /* Convert *TP to a time_t value.  */
578 time_t
579 mktime (struct tm *tp)
580 {
581 #ifdef _LIBC
582   /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
583      time zone names contained in the external variable 'tzname' shall
584      be set as if the tzset() function had been called.  */
585   __tzset ();
586 #endif
587
588   return __mktime_internal (tp, __localtime_r, &localtime_offset);
589 }
590
591 #ifdef weak_alias
592 weak_alias (mktime, timelocal)
593 #endif
594
595 #ifdef _LIBC
596 libc_hidden_def (mktime)
597 libc_hidden_weak (timelocal)
598 #endif
599 \f
600 #if DEBUG
601
602 static int
603 not_equal_tm (const struct tm *a, const struct tm *b)
604 {
605   return ((a->tm_sec ^ b->tm_sec)
606           | (a->tm_min ^ b->tm_min)
607           | (a->tm_hour ^ b->tm_hour)
608           | (a->tm_mday ^ b->tm_mday)
609           | (a->tm_mon ^ b->tm_mon)
610           | (a->tm_year ^ b->tm_year)
611           | (a->tm_yday ^ b->tm_yday)
612           | isdst_differ (a->tm_isdst, b->tm_isdst));
613 }
614
615 static void
616 print_tm (const struct tm *tp)
617 {
618   if (tp)
619     printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
620             tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
621             tp->tm_hour, tp->tm_min, tp->tm_sec,
622             tp->tm_yday, tp->tm_wday, tp->tm_isdst);
623   else
624     printf ("0");
625 }
626
627 static int
628 check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
629 {
630   if (tk != tl || !lt || not_equal_tm (&tmk, lt))
631     {
632       printf ("mktime (");
633       print_tm (lt);
634       printf (")\nyields (");
635       print_tm (&tmk);
636       printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
637       return 1;
638     }
639
640   return 0;
641 }
642
643 int
644 main (int argc, char **argv)
645 {
646   int status = 0;
647   struct tm tm, tmk, tml;
648   struct tm *lt;
649   time_t tk, tl, tl1;
650   char trailer;
651
652   if ((argc == 3 || argc == 4)
653       && (sscanf (argv[1], "%d-%d-%d%c",
654                   &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
655           == 3)
656       && (sscanf (argv[2], "%d:%d:%d%c",
657                   &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
658           == 3))
659     {
660       tm.tm_year -= TM_YEAR_BASE;
661       tm.tm_mon--;
662       tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
663       tmk = tm;
664       tl = mktime (&tmk);
665       lt = localtime (&tl);
666       if (lt)
667         {
668           tml = *lt;
669           lt = &tml;
670         }
671       printf ("mktime returns %ld == ", (long int) tl);
672       print_tm (&tmk);
673       printf ("\n");
674       status = check_result (tl, tmk, tl, lt);
675     }
676   else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
677     {
678       time_t from = atol (argv[1]);
679       time_t by = atol (argv[2]);
680       time_t to = atol (argv[3]);
681
682       if (argc == 4)
683         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
684           {
685             lt = localtime (&tl);
686             if (lt)
687               {
688                 tmk = tml = *lt;
689                 tk = mktime (&tmk);
690                 status |= check_result (tk, tmk, tl, &tml);
691               }
692             else
693               {
694                 printf ("localtime (%ld) yields 0\n", (long int) tl);
695                 status = 1;
696               }
697             tl1 = tl + by;
698             if ((tl1 < tl) != (by < 0))
699               break;
700           }
701       else
702         for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
703           {
704             /* Null benchmark.  */
705             lt = localtime (&tl);
706             if (lt)
707               {
708                 tmk = tml = *lt;
709                 tk = tl;
710                 status |= check_result (tk, tmk, tl, &tml);
711               }
712             else
713               {
714                 printf ("localtime (%ld) yields 0\n", (long int) tl);
715                 status = 1;
716               }
717             tl1 = tl + by;
718             if ((tl1 < tl) != (by < 0))
719               break;
720           }
721     }
722   else
723     printf ("Usage:\
724 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
725 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
726 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
727             argv[0], argv[0], argv[0]);
728
729   return status;
730 }
731
732 #endif /* DEBUG */
733 \f
734 /*
735 Local Variables:
736 compile-command: "gcc -DDEBUG -I. -Wall -W -O2 -g mktime.c -o mktime"
737 End:
738 */