(iso-languages): For Portuguese ~c and
[bpt/emacs.git] / src / mktime.c
1 /* Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
2 Contributed by Paul Eggert (eggert@twinsun.com).
3
4 NOTE: The canonical source of this file is maintained with the GNU C Library.
5 Bugs can be reported to bug-glibc@gnu.org.
6
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA. */
21
22 /* Define this to have a standalone program to test this implementation of
23 mktime. */
24 /* #define DEBUG 1 */
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 /* Some systems need this in order to declare localtime_r properly. */
31 #ifndef _REENTRANT
32 # define _REENTRANT 1
33 #endif
34
35 #ifdef _LIBC
36 # define HAVE_LIMITS_H 1
37 # define HAVE_LOCALTIME_R 1
38 # define STDC_HEADERS 1
39 #endif
40
41 /* Assume that leap seconds are possible, unless told otherwise.
42 If the host has a `zic' command with a `-L leapsecondfilename' option,
43 then it supports leap seconds; otherwise it probably doesn't. */
44 #ifndef LEAP_SECONDS_POSSIBLE
45 # define LEAP_SECONDS_POSSIBLE 1
46 #endif
47
48 #include <sys/types.h> /* Some systems define `time_t' here. */
49 #include <time.h>
50
51 #if HAVE_LIMITS_H
52 # include <limits.h>
53 #endif
54
55 #if DEBUG
56 # include <stdio.h>
57 # if STDC_HEADERS
58 # include <stdlib.h>
59 # endif
60 /* Make it work even if the system's libc has its own mktime routine. */
61 # define mktime my_mktime
62 #endif /* DEBUG */
63
64 #ifndef __P
65 # if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
66 # define __P(args) args
67 # else
68 # define __P(args) ()
69 # endif /* GCC. */
70 #endif /* Not __P. */
71
72 #ifndef CHAR_BIT
73 # define CHAR_BIT 8
74 #endif
75
76 /* The extra casts work around common compiler bugs. */
77 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
78 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
79 It is necessary at least when t == time_t. */
80 #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
81 ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
82 #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
83
84 #ifndef INT_MIN
85 # define INT_MIN TYPE_MINIMUM (int)
86 #endif
87 #ifndef INT_MAX
88 # define INT_MAX TYPE_MAXIMUM (int)
89 #endif
90
91 #ifndef TIME_T_MIN
92 # define TIME_T_MIN TYPE_MINIMUM (time_t)
93 #endif
94 #ifndef TIME_T_MAX
95 # define TIME_T_MAX TYPE_MAXIMUM (time_t)
96 #endif
97
98 #define TM_YEAR_BASE 1900
99 #define EPOCH_YEAR 1970
100
101 #ifndef __isleap
102 /* Nonzero if YEAR is a leap year (every 4 years,
103 except every 100th isn't, and every 400th is). */
104 # define __isleap(year) \
105 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
106 #endif
107
108 /* How many days come before each month (0-12). */
109 const unsigned short int __mon_yday[2][13] =
110 {
111 /* Normal years. */
112 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
113 /* Leap years. */
114 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
115 };
116
117 static struct tm *ranged_convert __P ((struct tm *(*) __P ((const time_t *,
118 struct tm *)),
119 time_t *, struct tm *));
120 static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
121 time_t __mktime_internal __P ((struct tm *,
122 struct tm *(*) (const time_t *, struct tm *),
123 time_t *));
124
125
126 #ifdef _LIBC
127 # define localtime_r __localtime_r
128 #else
129 # if ! HAVE_LOCALTIME_R && ! defined localtime_r
130 /* Approximate localtime_r as best we can in its absence. */
131 # define localtime_r my_mktime_localtime_r
132 static struct tm *localtime_r __P ((const time_t *, struct tm *));
133 static struct tm *
134 localtime_r (t, tp)
135 const time_t *t;
136 struct tm *tp;
137 {
138 struct tm *l = localtime (t);
139 if (! l)
140 return 0;
141 *tp = *l;
142 return tp;
143 }
144 # endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
145 #endif /* ! _LIBC */
146
147
148 /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
149 measured in seconds, ignoring leap seconds.
150 YEAR uses the same numbering as TM->tm_year.
151 All values are in range, except possibly YEAR.
152 If TP is null, return a nonzero value.
153 If overflow occurs, yield the low order bits of the correct answer. */
154 static time_t
155 ydhms_tm_diff (year, yday, hour, min, sec, tp)
156 int year, yday, hour, min, sec;
157 const struct tm *tp;
158 {
159 if (!tp)
160 return 1;
161 else
162 {
163 /* Compute intervening leap days correctly even if year is negative.
164 Take care to avoid int overflow. time_t overflow is OK, since
165 only the low order bits of the correct time_t answer are needed.
166 Don't convert to time_t until after all divisions are done, since
167 time_t might be unsigned. */
168 int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
169 int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
170 int a100 = a4 / 25 - (a4 % 25 < 0);
171 int b100 = b4 / 25 - (b4 % 25 < 0);
172 int a400 = a100 >> 2;
173 int b400 = b100 >> 2;
174 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
175 time_t years = year - (time_t) tp->tm_year;
176 time_t days = (365 * years + intervening_leap_days
177 + (yday - tp->tm_yday));
178 return (60 * (60 * (24 * days + (hour - tp->tm_hour))
179 + (min - tp->tm_min))
180 + (sec - tp->tm_sec));
181 }
182 }
183
184
185 static time_t localtime_offset;
186
187 /* Convert *TP to a time_t value. */
188 time_t
189 mktime (tp)
190 struct tm *tp;
191 {
192 #ifdef _LIBC
193 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
194 time zone names contained in the external variable `tzname' shall
195 be set as if the tzset() function had been called. */
196 __tzset ();
197 #endif
198
199 return __mktime_internal (tp, localtime_r, &localtime_offset);
200 }
201
202 /* Use CONVERT to convert *T to a broken down time in *TP.
203 If *T is out of range for conversion, adjust it so that
204 it is the nearest in-range value and then convert that. */
205 static struct tm *
206 ranged_convert (convert, t, tp)
207 struct tm *(*convert) __P ((const time_t *, struct tm *));
208 time_t *t;
209 struct tm *tp;
210 {
211 struct tm *r;
212
213 if (! (r = (*convert) (t, tp)) && *t)
214 {
215 time_t bad = *t;
216 time_t ok = 0;
217 struct tm tm;
218
219 /* BAD is a known unconvertible time_t, and OK is a known good one.
220 Use binary search to narrow the range between BAD and OK until
221 they differ by 1. */
222 while (bad != ok + (bad < 0 ? -1 : 1))
223 {
224 time_t mid = *t = (bad < 0
225 ? bad + ((ok - bad) >> 1)
226 : ok + ((bad - ok) >> 1));
227 if ((r = (*convert) (t, tp)))
228 {
229 tm = *r;
230 ok = mid;
231 }
232 else
233 bad = mid;
234 }
235
236 if (!r && ok)
237 {
238 /* The last conversion attempt failed;
239 revert to the most recent successful attempt. */
240 *t = ok;
241 *tp = tm;
242 r = tp;
243 }
244 }
245
246 return r;
247 }
248
249
250 /* Convert *TP to a time_t value, inverting
251 the monotonic and mostly-unit-linear conversion function CONVERT.
252 Use *OFFSET to keep track of a guess at the offset of the result,
253 compared to what the result would be for UTC without leap seconds.
254 If *OFFSET's guess is correct, only one CONVERT call is needed. */
255 time_t
256 __mktime_internal (tp, convert, offset)
257 struct tm *tp;
258 struct tm *(*convert) __P ((const time_t *, struct tm *));
259 time_t *offset;
260 {
261 time_t t, dt, t0;
262 struct tm tm;
263
264 /* The maximum number of probes (calls to CONVERT) should be enough
265 to handle any combinations of time zone rule changes, solar time,
266 and leap seconds. POSIX.1 prohibits leap seconds, but some hosts
267 have them anyway. */
268 int remaining_probes = 4;
269
270 /* Time requested. Copy it in case CONVERT modifies *TP; this can
271 occur if TP is localtime's returned value and CONVERT is localtime. */
272 int sec = tp->tm_sec;
273 int min = tp->tm_min;
274 int hour = tp->tm_hour;
275 int mday = tp->tm_mday;
276 int mon = tp->tm_mon;
277 int year_requested = tp->tm_year;
278 int isdst = tp->tm_isdst;
279
280 /* Ensure that mon is in range, and set year accordingly. */
281 int mon_remainder = mon % 12;
282 int negative_mon_remainder = mon_remainder < 0;
283 int mon_years = mon / 12 - negative_mon_remainder;
284 int year = year_requested + mon_years;
285
286 /* The other values need not be in range:
287 the remaining code handles minor overflows correctly,
288 assuming int and time_t arithmetic wraps around.
289 Major overflows are caught at the end. */
290
291 /* Calculate day of year from year, month, and day of month.
292 The result need not be in range. */
293 int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
294 [mon_remainder + 12 * negative_mon_remainder])
295 + mday - 1);
296
297 int sec_requested = sec;
298 #if LEAP_SECONDS_POSSIBLE
299 /* Handle out-of-range seconds specially,
300 since ydhms_tm_diff assumes every minute has 60 seconds. */
301 if (sec < 0)
302 sec = 0;
303 if (59 < sec)
304 sec = 59;
305 #endif
306
307 /* Invert CONVERT by probing. First assume the same offset as last time.
308 Then repeatedly use the error to improve the guess. */
309
310 tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
311 tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
312 t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
313
314 for (t = t0 + *offset;
315 (dt = ydhms_tm_diff (year, yday, hour, min, sec,
316 ranged_convert (convert, &t, &tm)));
317 t += dt)
318 if (--remaining_probes == 0)
319 return -1;
320
321 /* Check whether tm.tm_isdst has the requested value, if any. */
322 if (0 <= isdst && 0 <= tm.tm_isdst)
323 {
324 int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
325 if (dst_diff)
326 {
327 /* Move two hours in the direction indicated by the disagreement,
328 probe some more, and switch to a new time if found.
329 The largest known fallback due to daylight savings is two hours:
330 once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
331 time_t ot = t - 2 * 60 * 60 * dst_diff;
332 while (--remaining_probes != 0)
333 {
334 struct tm otm;
335 if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
336 ranged_convert (convert, &ot, &otm))))
337 {
338 t = ot;
339 tm = otm;
340 break;
341 }
342 if ((ot += dt) == t)
343 break; /* Avoid a redundant probe. */
344 }
345 }
346 }
347
348 *offset = t - t0;
349
350 #if LEAP_SECONDS_POSSIBLE
351 if (sec_requested != tm.tm_sec)
352 {
353 /* Adjust time to reflect the tm_sec requested, not the normalized value.
354 Also, repair any damage from a false match due to a leap second. */
355 t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
356 if (! (*convert) (&t, &tm))
357 return -1;
358 }
359 #endif
360
361 if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
362 {
363 /* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
364 so check for major overflows. A gross check suffices,
365 since if t has overflowed, it is off by a multiple of
366 TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
367 the difference that is bounded by a small value. */
368
369 double dyear = (double) year_requested + mon_years - tm.tm_year;
370 double dday = 366 * dyear + mday;
371 double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
372
373 /* On Irix4.0.5 cc, dividing TIME_T_MIN by 3 does not produce
374 correct results, ie., it erroneously gives a positive value
375 of 715827882. Setting a variable first then doing math on it
376 seems to work. (ghazi@caip.rutgers.edu) */
377
378 const time_t time_t_max = TIME_T_MAX;
379 const time_t time_t_min = TIME_T_MIN;
380
381 if (time_t_max / 3 - time_t_min / 3 < (dsec < 0 ? - dsec : dsec))
382 return -1;
383 }
384
385 *tp = tm;
386 return t;
387 }
388
389 #ifdef weak_alias
390 weak_alias (mktime, timelocal)
391 #endif
392 \f
393 #if DEBUG
394
395 static int
396 not_equal_tm (a, b)
397 struct tm *a;
398 struct tm *b;
399 {
400 return ((a->tm_sec ^ b->tm_sec)
401 | (a->tm_min ^ b->tm_min)
402 | (a->tm_hour ^ b->tm_hour)
403 | (a->tm_mday ^ b->tm_mday)
404 | (a->tm_mon ^ b->tm_mon)
405 | (a->tm_year ^ b->tm_year)
406 | (a->tm_mday ^ b->tm_mday)
407 | (a->tm_yday ^ b->tm_yday)
408 | (a->tm_isdst ^ b->tm_isdst));
409 }
410
411 static void
412 print_tm (tp)
413 struct tm *tp;
414 {
415 if (tp)
416 printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
417 tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
418 tp->tm_hour, tp->tm_min, tp->tm_sec,
419 tp->tm_yday, tp->tm_wday, tp->tm_isdst);
420 else
421 printf ("0");
422 }
423
424 static int
425 check_result (tk, tmk, tl, lt)
426 time_t tk;
427 struct tm tmk;
428 time_t tl;
429 struct tm *lt;
430 {
431 if (tk != tl || !lt || not_equal_tm (&tmk, lt))
432 {
433 printf ("mktime (");
434 print_tm (&tmk);
435 printf (")\nyields (");
436 print_tm (lt);
437 printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
438 return 1;
439 }
440
441 return 0;
442 }
443
444 int
445 main (argc, argv)
446 int argc;
447 char **argv;
448 {
449 int status = 0;
450 struct tm tm, tmk, tml;
451 struct tm *lt;
452 time_t tk, tl;
453 char trailer;
454
455 if ((argc == 3 || argc == 4)
456 && (sscanf (argv[1], "%d-%d-%d%c",
457 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
458 == 3)
459 && (sscanf (argv[2], "%d:%d:%d%c",
460 &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
461 == 3))
462 {
463 tm.tm_year -= TM_YEAR_BASE;
464 tm.tm_mon--;
465 tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
466 tmk = tm;
467 tl = mktime (&tmk);
468 lt = localtime (&tl);
469 if (lt)
470 {
471 tml = *lt;
472 lt = &tml;
473 }
474 printf ("mktime returns %ld == ", (long) tl);
475 print_tm (&tmk);
476 printf ("\n");
477 status = check_result (tl, tmk, tl, lt);
478 }
479 else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
480 {
481 time_t from = atol (argv[1]);
482 time_t by = atol (argv[2]);
483 time_t to = atol (argv[3]);
484
485 if (argc == 4)
486 for (tl = from; tl <= to; tl += by)
487 {
488 lt = localtime (&tl);
489 if (lt)
490 {
491 tmk = tml = *lt;
492 tk = mktime (&tmk);
493 status |= check_result (tk, tmk, tl, tml);
494 }
495 else
496 {
497 printf ("localtime (%ld) yields 0\n", (long) tl);
498 status = 1;
499 }
500 }
501 else
502 for (tl = from; tl <= to; tl += by)
503 {
504 /* Null benchmark. */
505 lt = localtime (&tl);
506 if (lt)
507 {
508 tmk = tml = *lt;
509 tk = tl;
510 status |= check_result (tk, tmk, tl, tml);
511 }
512 else
513 {
514 printf ("localtime (%ld) yields 0\n", (long) tl);
515 status = 1;
516 }
517 }
518 }
519 else
520 printf ("Usage:\
521 \t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
522 \t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
523 \t%s FROM BY TO - # Do not test those values (for benchmark).\n",
524 argv[0], argv[0], argv[0]);
525
526 return status;
527 }
528
529 #endif /* DEBUG */
530 \f
531 /*
532 Local Variables:
533 compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
534 End:
535 */