]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/mktime.c
mktime: improve heuristic for ca-1986 Indiana DST
[thirdparty/glibc.git] / time / mktime.c
CommitLineData
6226efbd 1/* Convert a 'struct tm' to a time_t value.
581c785b 2 Copyright (C) 1993-2022 Free Software Foundation, Inc.
5290baf0 3 This file is part of the GNU C Library.
41aba3d7 4 Contributed by Paul Eggert <eggert@twinsun.com>.
28f540f4 5
5290baf0 6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
28f540f4 10
5290baf0
UD
11 The GNU C Library 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 GNU
41bdb6e2 14 Lesser General Public License for more details.
28f540f4 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6 17 License along with the GNU C Library; if not, see
8e6fd2bd 18 <https://www.gnu.org/licenses/>. */
28f540f4 19
8e6fd2bd
PE
20/* The following macros influence what gets defined when this file is compiled:
21
22 Macro/expression Which gnulib module This compilation unit
23 should define
24
25 _LIBC (glibc proper) mktime
26
27 NEED_MKTIME_WORKING mktime rpl_mktime
28 || NEED_MKTIME_WINDOWS
29
30 NEED_MKTIME_INTERNAL mktime-internal mktime_internal
8e6fd2bd
PE
31 */
32
5d8af156 33#ifndef _LIBC
de20b81a 34# include <libc-config.h>
28f540f4
RM
35#endif
36
80fd7387 37/* Assume that leap seconds are possible, unless told otherwise.
6226efbd 38 If the host has a 'zic' command with a '-L leapsecondfilename' option,
80fd7387
RM
39 then it supports leap seconds; otherwise it probably doesn't. */
40#ifndef LEAP_SECONDS_POSSIBLE
9c2322bc 41# define LEAP_SECONDS_POSSIBLE 1
80fd7387
RM
42#endif
43
28f540f4
RM
44#include <time.h>
45
de20b81a 46#include <errno.h>
85e07670 47#include <limits.h>
8e6fd2bd
PE
48#include <stdbool.h>
49#include <stdlib.h>
50#include <string.h>
28f540f4 51
8e6fd2bd
PE
52#include <intprops.h>
53#include <verify.h>
9b5204dd 54
8e6fd2bd
PE
55#ifndef NEED_MKTIME_INTERNAL
56# define NEED_MKTIME_INTERNAL 0
57#endif
58#ifndef NEED_MKTIME_WINDOWS
59# define NEED_MKTIME_WINDOWS 0
60#endif
61#ifndef NEED_MKTIME_WORKING
5d8af156 62# define NEED_MKTIME_WORKING 0
8e6fd2bd
PE
63#endif
64
65#include "mktime-internal.h"
66
5a580643 67#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
8e6fd2bd
PE
68static void
69my_tzset (void)
70{
71# if NEED_MKTIME_WINDOWS
72 /* Rectify the value of the environment variable TZ.
73 There are four possible kinds of such values:
74 - Traditional US time zone names, e.g. "PST8PDT". Syntax: see
78919d38 75 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
8e6fd2bd
PE
76 - Time zone names based on geography, that contain one or more
77 slashes, e.g. "Europe/Moscow".
78 - Time zone names based on geography, without slashes, e.g.
79 "Singapore".
80 - Time zone names that contain explicit DST rules. Syntax: see
f8042536 81 <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
8e6fd2bd
PE
82 The Microsoft CRT understands only the first kind. It produces incorrect
83 results if the value of TZ is of the other kinds.
84 But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
85 of the second kind for most geographies, or of the first kind in a few
86 other geographies. If it is of the second kind, neutralize it. For the
87 Microsoft CRT, an absent or empty TZ means the time zone that the user
88 has set in the Windows Control Panel.
89 If the value of TZ is of the third or fourth kind -- Cygwin programs
90 understand these syntaxes as well --, it does not matter whether we
91 neutralize it or not, since these values occur only when a Cygwin user
92 has set TZ explicitly; this case is 1. rare and 2. under the user's
93 responsibility. */
94 const char *tz = getenv ("TZ");
95 if (tz != NULL && strchr (tz, '/') != NULL)
96 _putenv ("TZ=");
82a1ec85 97# else
8e6fd2bd 98 tzset ();
62bdf9a6 99# endif
8e6fd2bd
PE
100}
101# undef __tzset
102# define __tzset() my_tzset ()
62bdf9a6
PE
103#endif
104
8e6fd2bd
PE
105#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
106
107/* A signed type that can represent an integer number of years
efbdddc3 108 multiplied by four times the number of seconds in a year. It is
8e6fd2bd 109 needed when converting a tm_year value times the number of seconds
efbdddc3 110 in a year. The factor of four comes because these products need
8e6fd2bd 111 to be subtracted from each other, and sometimes with an offset
efbdddc3
PE
112 added to them, and then with another timestamp added, without
113 worrying about overflow.
8e6fd2bd 114
20aa5819
PE
115 Much of the code uses long_int to represent __time64_t values, to
116 lessen the hassle of dealing with platforms where __time64_t is
8e6fd2bd 117 unsigned, and because long_int should suffice to represent all
20aa5819
PE
118 __time64_t values that mktime can generate even on platforms where
119 __time64_t is wider than the int components of struct tm. */
f04dfbc2 120
efbdddc3 121#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
f04dfbc2
PE
122typedef long int long_int;
123#else
124typedef long long int long_int;
125#endif
efbdddc3 126verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
f04dfbc2 127
1c67fabd 128/* Shift A right by B bits portably, by dividing A by 2**B and
8e6fd2bd
PE
129 truncating towards minus infinity. B should be in the range 0 <= B
130 <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful
131 bits in a long_int. LONG_INT_BITS is at least 32.
1c67fabd
RM
132
133 ISO C99 says that A >> B is implementation-defined if A < 0. Some
134 implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
135 right in the usual way when A < 0, so SHR falls back on division if
136 ordinary A >> B doesn't seem to be the usual signed shift. */
28f540f4 137
8e6fd2bd
PE
138static long_int
139shr (long_int a, int b)
140{
141 long_int one = 1;
142 return (-one >> 1 == -1
143 ? a >> b
db10cd9e 144 : (a + (a < 0)) / (one << b) - (a < 0));
8e6fd2bd
PE
145}
146
20aa5819 147/* Bounds for the intersection of __time64_t and long_int. */
8e6fd2bd
PE
148
149static long_int const mktime_min
20aa5819
PE
150 = ((TYPE_SIGNED (__time64_t)
151 && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
152 ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
8e6fd2bd 153static long_int const mktime_max
20aa5819
PE
154 = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
155 ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
a28a0500 156
80fd7387 157#define EPOCH_YEAR 1970
a28a0500 158#define TM_YEAR_BASE 1900
8e6fd2bd 159verify (TM_YEAR_BASE % 100 == 0);
28f540f4 160
8e6fd2bd
PE
161/* Is YEAR + TM_YEAR_BASE a leap year? */
162static bool
f04dfbc2 163leapyear (long_int year)
72035294
RM
164{
165 /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
166 Also, work even if YEAR is negative. */
167 return
168 ((year & 3) == 0
169 && (year % 100 != 0
170 || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
171}
28f540f4 172
80fd7387 173/* How many days come before each month (0-12). */
8592ae92
UD
174#ifndef _LIBC
175static
176#endif
80fd7387
RM
177const unsigned short int __mon_yday[2][13] =
178 {
179 /* Normal years. */
180 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
181 /* Leap years. */
182 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
183 };
28f540f4 184
28f540f4 185
8e6fd2bd
PE
186/* Do the values A and B differ according to the rules for tm_isdst?
187 A and B differ if one is zero and the other positive. */
188static bool
ce73d683
PE
189isdst_differ (int a, int b)
190{
191 return (!a != !b) && (0 <= a) && (0 <= b);
192}
193
e507cc56
RM
194/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
195 (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
8e6fd2bd 196 were not adjusted between the timestamps.
80fd7387 197
e507cc56 198 The YEAR values uses the same numbering as TP->tm_year. Values
efbdddc3
PE
199 need not be in the usual range. However, YEAR1 - YEAR0 must not
200 overflow even when multiplied by three times the number of seconds
201 in a year, and likewise for YDAY1 - YDAY0 and three times the
202 number of seconds in a day. */
e507cc56 203
8e6fd2bd 204static long_int
f04dfbc2 205ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
e507cc56
RM
206 int year0, int yday0, int hour0, int min0, int sec0)
207{
8e6fd2bd 208 verify (-1 / 2 == 0);
e507cc56
RM
209
210 /* Compute intervening leap days correctly even if year is negative.
211 Take care to avoid integer overflow here. */
8e6fd2bd
PE
212 int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
213 int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
db10cd9e
PE
214 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
215 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
8e6fd2bd
PE
216 int a400 = shr (a100, 2);
217 int b400 = shr (b100, 2);
e507cc56
RM
218 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
219
8e6fd2bd
PE
220 /* Compute the desired time without overflowing. */
221 long_int years = year1 - year0;
222 long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
223 long_int hours = 24 * days + hour1 - hour0;
224 long_int minutes = 60 * hours + min1 - min0;
225 long_int seconds = 60 * minutes + sec1 - sec0;
e507cc56
RM
226 return seconds;
227}
228
8e6fd2bd
PE
229/* Return the average of A and B, even if A + B would overflow.
230 Round toward positive infinity. */
231static long_int
232long_int_avg (long_int a, long_int b)
62bdf9a6 233{
8e6fd2bd 234 return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
62bdf9a6 235}
e507cc56 236
86aece3b
PE
237/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC)
238 minus *TP seconds, assuming no clock adjustments occurred between
239 the two timestamps.
240
8e6fd2bd
PE
241 YEAR and YDAY must not be so large that multiplying them by three times the
242 number of seconds in a year (or day, respectively) would overflow long_int.
86aece3b 243 *TP should be in the usual range. */
8e6fd2bd 244static long_int
86aece3b
PE
245tm_diff (long_int year, long_int yday, int hour, int min, int sec,
246 struct tm const *tp)
80fd7387 247{
86aece3b
PE
248 return ydhms_diff (year, yday, hour, min, sec,
249 tp->tm_year, tp->tm_yday,
250 tp->tm_hour, tp->tm_min, tp->tm_sec);
8e6fd2bd
PE
251}
252
253/* Use CONVERT to convert T to a struct tm value in *TM. T must be in
20aa5819 254 range for __time64_t. Return TM if successful, NULL (setting errno) on
86aece3b 255 failure. */
8e6fd2bd 256static struct tm *
20aa5819 257convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
8e6fd2bd
PE
258 long_int t, struct tm *tm)
259{
20aa5819 260 __time64_t x = t;
8e6fd2bd 261 return convert (&x, tm);
80fd7387
RM
262}
263
fe0ec73e
UD
264/* Use CONVERT to convert *T to a broken down time in *TP.
265 If *T is out of range for conversion, adjust it so that
8e6fd2bd 266 it is the nearest in-range value and then convert that.
20aa5819 267 A value is in range if it fits in both __time64_t and long_int.
86aece3b 268 Return TP on success, NULL (setting errno) on failure. */
fe0ec73e 269static struct tm *
20aa5819 270ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
8e6fd2bd 271 long_int *t, struct tm *tp)
fe0ec73e 272{
86aece3b
PE
273 long_int t1 = (*t < mktime_min ? mktime_min
274 : *t <= mktime_max ? *t : mktime_max);
275 struct tm *r = convert_time (convert, t1, tp);
276 if (r)
fe0ec73e 277 {
86aece3b
PE
278 *t = t1;
279 return r;
280 }
281 if (errno != EOVERFLOW)
282 return NULL;
fe0ec73e 283
86aece3b
PE
284 long_int bad = t1;
285 long_int ok = 0;
286 struct tm oktm; oktm.tm_sec = -1;
f6b3331b 287
86aece3b
PE
288 /* BAD is a known out-of-range value, and OK is a known in-range one.
289 Use binary search to narrow the range between BAD and OK until
290 they differ by 1. */
291 while (true)
292 {
293 long_int mid = long_int_avg (ok, bad);
294 if (mid == ok || mid == bad)
295 break;
296 if (convert_time (convert, mid, tp))
297 ok = mid, oktm = *tp;
298 else if (errno != EOVERFLOW)
299 return NULL;
300 else
301 bad = mid;
fe0ec73e
UD
302 }
303
86aece3b
PE
304 if (oktm.tm_sec < 0)
305 return NULL;
306 *t = ok;
307 *tp = oktm;
308 return tp;
fe0ec73e
UD
309}
310
311
20aa5819 312/* Convert *TP to a __time64_t value, inverting
80fd7387
RM
313 the monotonic and mostly-unit-linear conversion function CONVERT.
314 Use *OFFSET to keep track of a guess at the offset of the result,
315 compared to what the result would be for UTC without leap seconds.
e507cc56 316 If *OFFSET's guess is correct, only one CONVERT call is needed.
de20b81a
PE
317 If successful, set *TP to the canonicalized struct tm;
318 otherwise leave *TP alone, return ((time_t) -1) and set errno.
e507cc56 319 This function is external because it is used also by timegm.c. */
20aa5819 320__time64_t
eda78eec 321__mktime_internal (struct tm *tp,
20aa5819 322 struct tm *(*convert) (const __time64_t *, struct tm *),
8e6fd2bd 323 mktime_offset_t *offset)
28f540f4 324{
80fd7387
RM
325 struct tm tm;
326
327 /* The maximum number of probes (calls to CONVERT) should be enough
328 to handle any combinations of time zone rule changes, solar time,
25b3b17b
UD
329 leap seconds, and oscillations around a spring-forward gap.
330 POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
331 int remaining_probes = 6;
80fd7387
RM
332
333 /* Time requested. Copy it in case CONVERT modifies *TP; this can
334 occur if TP is localtime's returned value and CONVERT is localtime. */
335 int sec = tp->tm_sec;
336 int min = tp->tm_min;
337 int hour = tp->tm_hour;
338 int mday = tp->tm_mday;
339 int mon = tp->tm_mon;
340 int year_requested = tp->tm_year;
ce73d683 341 int isdst = tp->tm_isdst;
80fd7387 342
b5ef404e 343 /* 1 if the previous probe was DST. */
86aece3b 344 int dst2 = 0;
b5ef404e 345
80fd7387
RM
346 /* Ensure that mon is in range, and set year accordingly. */
347 int mon_remainder = mon % 12;
348 int negative_mon_remainder = mon_remainder < 0;
349 int mon_years = mon / 12 - negative_mon_remainder;
f04dfbc2
PE
350 long_int lyear_requested = year_requested;
351 long_int year = lyear_requested + mon_years;
80fd7387 352
8592ae92 353 /* The other values need not be in range:
8e6fd2bd 354 the remaining code handles overflows correctly. */
80fd7387
RM
355
356 /* Calculate day of year from year, month, and day of month.
357 The result need not be in range. */
e507cc56
RM
358 int mon_yday = ((__mon_yday[leapyear (year)]
359 [mon_remainder + 12 * negative_mon_remainder])
360 - 1);
f04dfbc2
PE
361 long_int lmday = mday;
362 long_int yday = mon_yday + lmday;
e507cc56 363
8e6fd2bd
PE
364 mktime_offset_t off = *offset;
365 int negative_offset_guess;
80fd7387 366
9a0a462c 367 int sec_requested = sec;
55544141 368
e507cc56
RM
369 if (LEAP_SECONDS_POSSIBLE)
370 {
371 /* Handle out-of-range seconds specially,
efbdddc3 372 since ydhms_diff assumes every minute has 60 seconds. */
e507cc56
RM
373 if (sec < 0)
374 sec = 0;
375 if (59 < sec)
376 sec = 59;
377 }
378
379 /* Invert CONVERT by probing. First assume the same offset as last
380 time. */
381
8e6fd2bd 382 INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
86aece3b
PE
383 long_int t0 = ydhms_diff (year, yday, hour, min, sec,
384 EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
385 negative_offset_guess);
386 long_int t = t0, t1 = t0, t2 = t0;
80fd7387 387
e507cc56 388 /* Repeatedly use the error to improve the guess. */
28f540f4 389
86aece3b
PE
390 while (true)
391 {
392 if (! ranged_convert (convert, &t, &tm))
de20b81a 393 return -1;
86aece3b
PE
394 long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
395 if (dt == 0)
396 break;
397
398 if (t == t1 && t != t2
399 && (tm.tm_isdst < 0
400 || (isdst < 0
401 ? dst2 <= (tm.tm_isdst != 0)
402 : (isdst != 0) != (tm.tm_isdst != 0))))
403 /* We can't possibly find a match, as we are oscillating
404 between two values. The requested time probably falls
405 within a spring-forward gap of size DT. Follow the common
406 practice in this case, which is to return a time that is DT
407 away from the requested time, preferring a time whose
408 tm_isdst differs from the requested value. (If no tm_isdst
409 was requested and only one of the two values has a nonzero
410 tm_isdst, prefer that value.) In practice, this is more
411 useful than returning -1. */
412 goto offset_found;
413
414 remaining_probes--;
415 if (remaining_probes == 0)
416 {
417 __set_errno (EOVERFLOW);
418 return -1;
419 }
420
421 t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
422 }
80fd7387 423
e507cc56 424 /* We have a match. Check whether tm.tm_isdst has the requested
25b3b17b 425 value, if any. */
ce73d683 426 if (isdst_differ (isdst, tm.tm_isdst))
80fd7387 427 {
c0016081
UD
428 /* tm.tm_isdst has the wrong value. Look for a neighboring
429 time with the right value, and use its UTC offset.
c0016081 430
e507cc56 431 Heuristic: probe the adjacent timestamps in both directions,
83859e11
PE
432 looking for the desired isdst. If none is found within a
433 reasonable duration bound, assume a one-hour DST difference.
434 This should work for all real time zone histories in the tz
435 database. */
436
437 /* +1 if we wanted standard time but got DST, -1 if the reverse. */
438 int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
e507cc56
RM
439
440 /* Distance between probes when looking for a DST boundary. In
441 tzdata2003a, the shortest period of DST is 601200 seconds
442 (e.g., America/Recife starting 2000-10-08 01:00), and the
443 shortest period of non-DST surrounded by DST is 694800
444 seconds (Africa/Tunis starting 1943-04-17 01:00). Use the
445 minimum of these two values, so we don't miss these short
446 periods when probing. */
447 int stride = 601200;
448
83859e11
PE
449 /* In TZDB 2021e, the longest period of DST (or of non-DST), in
450 which the DST (or adjacent DST) difference is not one hour,
451 is 457243209 seconds: e.g., America/Cambridge_Bay with leap
452 seconds, starting 1965-10-31 00:00 in a switch from
453 double-daylight time (-05) to standard time (-07), and
454 continuing to 1980-04-27 02:00 in a switch from standard time
455 (-07) to daylight time (-06). */
456 int duration_max = 457243209;
e507cc56
RM
457
458 /* Search in both directions, so the maximum distance is half
459 the duration; add the stride to avoid off-by-1 problems. */
460 int delta_bound = duration_max / 2 + stride;
461
462 int delta, direction;
463
464 for (delta = stride; delta < delta_bound; delta += stride)
465 for (direction = -1; direction <= 1; direction += 2)
8e6fd2bd
PE
466 {
467 long_int ot;
468 if (! INT_ADD_WRAPV (t, delta * direction, &ot))
469 {
470 struct tm otm;
86aece3b
PE
471 if (! ranged_convert (convert, &ot, &otm))
472 return -1;
8e6fd2bd
PE
473 if (! isdst_differ (isdst, otm.tm_isdst))
474 {
475 /* We found the desired tm_isdst.
476 Extrapolate back to the desired time. */
86aece3b
PE
477 long_int gt = ot + tm_diff (year, yday, hour, min, sec,
478 &otm);
479 if (mktime_min <= gt && gt <= mktime_max)
480 {
481 if (convert_time (convert, gt, &tm))
482 {
483 t = gt;
484 goto offset_found;
485 }
486 if (errno != EOVERFLOW)
487 return -1;
488 }
8e6fd2bd
PE
489 }
490 }
491 }
86aece3b 492
83859e11
PE
493 /* No unusual DST offset was found nearby. Assume one-hour DST. */
494 t += 60 * 60 * dst_difference;
495 if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
496 goto offset_found;
497
86aece3b
PE
498 __set_errno (EOVERFLOW);
499 return -1;
80fd7387 500 }
28f540f4 501
e507cc56 502 offset_found:
8e6fd2bd
PE
503 /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
504 This is just a heuristic to speed up the next mktime call, and
505 correctness is unaffected if integer overflow occurs here. */
6c90d759
PE
506 INT_SUBTRACT_WRAPV (t, t0, offset);
507 INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset);
80fd7387 508
e507cc56 509 if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
80fd7387
RM
510 {
511 /* Adjust time to reflect the tm_sec requested, not the normalized value.
512 Also, repair any damage from a false match due to a leap second. */
8e6fd2bd
PE
513 long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
514 sec_adjustment -= sec;
515 sec_adjustment += sec_requested;
516 if (INT_ADD_WRAPV (t, sec_adjustment, &t)
de20b81a
PE
517 || ! (mktime_min <= t && t <= mktime_max))
518 {
519 __set_errno (EOVERFLOW);
520 return -1;
521 }
522 if (! convert_time (convert, t, &tm))
78575a84
UD
523 return -1;
524 }
525
80fd7387
RM
526 *tp = tm;
527 return t;
528}
529
8e6fd2bd 530#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
eda78eec 531
8e6fd2bd 532#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
eda78eec 533
20aa5819
PE
534/* Convert *TP to a __time64_t value. */
535__time64_t
536__mktime64 (struct tm *tp)
eda78eec 537{
eda78eec 538 /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
6226efbd 539 time zone names contained in the external variable 'tzname' shall
eda78eec
UD
540 be set as if the tzset() function had been called. */
541 __tzset ();
eda78eec 542
8e6fd2bd
PE
543# if defined _LIBC || NEED_MKTIME_WORKING
544 static mktime_offset_t localtime_offset;
20aa5819 545 return __mktime_internal (tp, __localtime64_r, &localtime_offset);
8e6fd2bd
PE
546# else
547# undef mktime
548 return mktime (tp);
549# endif
eda78eec 550}
8e6fd2bd 551#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
eda78eec 552
20aa5819
PE
553#if defined _LIBC && __TIMESIZE != 64
554
555libc_hidden_def (__mktime64)
556
557time_t
558mktime (struct tm *tp)
559{
560 struct tm tm = *tp;
561 __time64_t t = __mktime64 (&tm);
562 if (in_time_t_range (t))
563 {
564 *tp = tm;
565 return t;
566 }
567 else
568 {
569 __set_errno (EOVERFLOW);
570 return -1;
571 }
572}
573
28f540f4 574#endif
c5598d47 575
20aa5819 576weak_alias (mktime, timelocal)
c5598d47
RM
577libc_hidden_def (mktime)
578libc_hidden_weak (timelocal)