Merge from emacs-23; up to 2010-05-28T19:18:47Z!juri@jurta.org.
[bpt/emacs.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 3, 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 */