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