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