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