mktime.c 18.1 KB
Newer Older
Paul Eggert's avatar
Paul Eggert committed
1
/* Convert a 'struct tm' to a time_t value.
Paul Eggert's avatar
Paul Eggert committed
2
   Copyright (C) 1993-2020 Free Software Foundation, Inc.
Paul Eggert's avatar
Paul Eggert committed
3 4 5
   This file is part of the GNU C Library.
   Contributed by Paul Eggert <eggert@twinsun.com>.

Paul Eggert's avatar
Paul Eggert committed
6 7 8 9
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.
Paul Eggert's avatar
Paul Eggert committed
10

Paul Eggert's avatar
Paul Eggert committed
11
   The GNU C Library is distributed in the hope that it will be useful,
Paul Eggert's avatar
Paul Eggert committed
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Paul Eggert's avatar
Paul Eggert committed
13 14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.
Paul Eggert's avatar
Paul Eggert committed
15

Paul Eggert's avatar
Paul Eggert committed
16 17
   You should have received a copy of the GNU General Public
   License along with the GNU C Library; if not, see
Paul Eggert's avatar
Paul Eggert committed
18
   <https://www.gnu.org/licenses/>.  */
Paul Eggert's avatar
Paul Eggert committed
19

Paul Eggert's avatar
Paul Eggert committed
20 21 22 23 24
/* The following macros influence what gets defined when this file is compiled:

   Macro/expression            Which gnulib module    This compilation unit
                                                      should define

Paul Eggert's avatar
Paul Eggert committed
25 26
   _LIBC                       (glibc proper)         mktime

Paul Eggert's avatar
Paul Eggert committed
27 28 29 30 31 32
   NEED_MKTIME_WORKING         mktime                 rpl_mktime
   || NEED_MKTIME_WINDOWS

   NEED_MKTIME_INTERNAL        mktime-internal        mktime_internal
 */

Paul Eggert's avatar
Paul Eggert committed
33 34
#ifndef _LIBC
# include <libc-config.h>
Paul Eggert's avatar
Paul Eggert committed
35 36 37
#endif

/* Assume that leap seconds are possible, unless told otherwise.
Paul Eggert's avatar
Paul Eggert committed
38
   If the host has a 'zic' command with a '-L leapsecondfilename' option,
Paul Eggert's avatar
Paul Eggert committed
39 40 41 42 43 44 45
   then it supports leap seconds; otherwise it probably doesn't.  */
#ifndef LEAP_SECONDS_POSSIBLE
# define LEAP_SECONDS_POSSIBLE 1
#endif

#include <time.h>

Paul Eggert's avatar
Paul Eggert committed
46
#include <errno.h>
Paul Eggert's avatar
Paul Eggert committed
47
#include <limits.h>
Paul Eggert's avatar
Paul Eggert committed
48
#include <stdbool.h>
Paul Eggert's avatar
Paul Eggert committed
49 50
#include <stdlib.h>
#include <string.h>
Paul Eggert's avatar
Paul Eggert committed
51

Paul Eggert's avatar
Paul Eggert committed
52 53
#include <intprops.h>
#include <verify.h>
Paul Eggert's avatar
Paul Eggert committed
54

Paul Eggert's avatar
Paul Eggert committed
55 56 57 58 59
#ifndef NEED_MKTIME_INTERNAL
# define NEED_MKTIME_INTERNAL 0
#endif
#ifndef NEED_MKTIME_WINDOWS
# define NEED_MKTIME_WINDOWS 0
Paul Eggert's avatar
Paul Eggert committed
60
#endif
Paul Eggert's avatar
Paul Eggert committed
61
#ifndef NEED_MKTIME_WORKING
Paul Eggert's avatar
Paul Eggert committed
62
# define NEED_MKTIME_WORKING 0
Paul Eggert's avatar
Paul Eggert committed
63 64 65
#endif

#include "mktime-internal.h"
Paul Eggert's avatar
Paul Eggert committed
66

Paul Eggert's avatar
Paul Eggert committed
67
#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
Paul Eggert's avatar
Paul Eggert committed
68 69 70 71 72 73 74
static void
my_tzset (void)
{
# if NEED_MKTIME_WINDOWS
  /* Rectify the value of the environment variable TZ.
     There are four possible kinds of such values:
       - Traditional US time zone names, e.g. "PST8PDT".  Syntax: see
Paul Eggert's avatar
Paul Eggert committed
75
         <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
Paul Eggert's avatar
Paul Eggert committed
76 77 78 79 80
       - Time zone names based on geography, that contain one or more
         slashes, e.g. "Europe/Moscow".
       - Time zone names based on geography, without slashes, e.g.
         "Singapore".
       - Time zone names that contain explicit DST rules.  Syntax: see
Paul Eggert's avatar
Paul Eggert committed
81
         <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
Paul Eggert's avatar
Paul Eggert committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
     The Microsoft CRT understands only the first kind.  It produces incorrect
     results if the value of TZ is of the other kinds.
     But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
     of the second kind for most geographies, or of the first kind in a few
     other geographies.  If it is of the second kind, neutralize it.  For the
     Microsoft CRT, an absent or empty TZ means the time zone that the user
     has set in the Windows Control Panel.
     If the value of TZ is of the third or fourth kind -- Cygwin programs
     understand these syntaxes as well --, it does not matter whether we
     neutralize it or not, since these values occur only when a Cygwin user
     has set TZ explicitly; this case is 1. rare and 2. under the user's
     responsibility.  */
  const char *tz = getenv ("TZ");
  if (tz != NULL && strchr (tz, '/') != NULL)
    _putenv ("TZ=");
# elif HAVE_TZSET
  tzset ();
# endif
}
# undef __tzset
# define __tzset() my_tzset ()
Paul Eggert's avatar
Paul Eggert committed
103 104
#endif

Paul Eggert's avatar
Paul Eggert committed
105
#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
Paul Eggert's avatar
Paul Eggert committed
106

Paul Eggert's avatar
Paul Eggert committed
107
/* A signed type that can represent an integer number of years
Paul Eggert's avatar
Paul Eggert committed
108
   multiplied by four times the number of seconds in a year.  It is
Paul Eggert's avatar
Paul Eggert committed
109
   needed when converting a tm_year value times the number of seconds
Paul Eggert's avatar
Paul Eggert committed
110
   in a year.  The factor of four comes because these products need
Paul Eggert's avatar
Paul Eggert committed
111
   to be subtracted from each other, and sometimes with an offset
Paul Eggert's avatar
Paul Eggert committed
112 113
   added to them, and then with another timestamp added, without
   worrying about overflow.
114

Paul Eggert's avatar
Paul Eggert committed
115 116
   Much of the code uses long_int to represent __time64_t values, to
   lessen the hassle of dealing with platforms where __time64_t is
Paul Eggert's avatar
Paul Eggert committed
117
   unsigned, and because long_int should suffice to represent all
Paul Eggert's avatar
Paul Eggert committed
118 119
   __time64_t values that mktime can generate even on platforms where
   __time64_t is wider than the int components of struct tm.  */
Paul Eggert's avatar
Paul Eggert committed
120

Paul Eggert's avatar
Paul Eggert committed
121
#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
122 123 124 125
typedef long int long_int;
#else
typedef long long int long_int;
#endif
Paul Eggert's avatar
Paul Eggert committed
126
verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
127

Paul Eggert's avatar
Paul Eggert committed
128
/* Shift A right by B bits portably, by dividing A by 2**B and
Paul Eggert's avatar
Paul Eggert committed
129 130 131
   truncating towards minus infinity.  B should be in the range 0 <= B
   <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful
   bits in a long_int.  LONG_INT_BITS is at least 32.
Paul Eggert's avatar
Paul Eggert committed
132 133 134 135 136 137

   ISO C99 says that A >> B is implementation-defined if A < 0.  Some
   implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift
   right in the usual way when A < 0, so SHR falls back on division if
   ordinary A >> B doesn't seem to be the usual signed shift.  */

Paul Eggert's avatar
Paul Eggert committed
138 139 140 141 142 143
static long_int
shr (long_int a, int b)
{
  long_int one = 1;
  return (-one >> 1 == -1
	  ? a >> b
Paul Eggert's avatar
Paul Eggert committed
144
	  : (a + (a < 0)) / (one << b) - (a < 0));
Paul Eggert's avatar
Paul Eggert committed
145 146
}

Paul Eggert's avatar
Paul Eggert committed
147
/* Bounds for the intersection of __time64_t and long_int.  */
Paul Eggert's avatar
Paul Eggert committed
148 149

static long_int const mktime_min
Paul Eggert's avatar
Paul Eggert committed
150 151 152
  = ((TYPE_SIGNED (__time64_t)
      && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
     ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
Paul Eggert's avatar
Paul Eggert committed
153
static long_int const mktime_max
Paul Eggert's avatar
Paul Eggert committed
154 155
  = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
     ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
Paul Eggert's avatar
Paul Eggert committed
156 157 158

#define EPOCH_YEAR 1970
#define TM_YEAR_BASE 1900
Paul Eggert's avatar
Paul Eggert committed
159
verify (TM_YEAR_BASE % 100 == 0);
Paul Eggert's avatar
Paul Eggert committed
160

Paul Eggert's avatar
Paul Eggert committed
161 162
/* Is YEAR + TM_YEAR_BASE a leap year?  */
static bool
163
leapyear (long_int year)
Paul Eggert's avatar
Paul Eggert committed
164 165 166 167 168 169
{
  /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
     Also, work even if YEAR is negative.  */
  return
    ((year & 3) == 0
     && (year % 100 != 0
Paul Eggert's avatar
Paul Eggert committed
170
	 || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
Paul Eggert's avatar
Paul Eggert committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
}

/* How many days come before each month (0-12).  */
#ifndef _LIBC
static
#endif
const unsigned short int __mon_yday[2][13] =
  {
    /* Normal years.  */
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
    /* Leap years.  */
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  };


Paul Eggert's avatar
Paul Eggert committed
186 187 188
/* Do the values A and B differ according to the rules for tm_isdst?
   A and B differ if one is zero and the other positive.  */
static bool
189 190
isdst_differ (int a, int b)
{
Paul Eggert's avatar
Paul Eggert committed
191
  return (!a != !b) && (0 <= a) && (0 <= b);
192 193
}

Paul Eggert's avatar
Paul Eggert committed
194 195
/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
Paul Eggert's avatar
Paul Eggert committed
196
   were not adjusted between the timestamps.
Paul Eggert's avatar
Paul Eggert committed
197 198

   The YEAR values uses the same numbering as TP->tm_year.  Values
Paul Eggert's avatar
Paul Eggert committed
199 200 201 202
   need not be in the usual range.  However, YEAR1 - YEAR0 must not
   overflow even when multiplied by three times the number of seconds
   in a year, and likewise for YDAY1 - YDAY0 and three times the
   number of seconds in a day.  */
Paul Eggert's avatar
Paul Eggert committed
203

Paul Eggert's avatar
Paul Eggert committed
204
static long_int
205
ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
Paul Eggert's avatar
Paul Eggert committed
206
	    int year0, int yday0, int hour0, int min0, int sec0)
Paul Eggert's avatar
Paul Eggert committed
207
{
Paul Eggert's avatar
Paul Eggert committed
208
  verify (-1 / 2 == 0);
Paul Eggert's avatar
Paul Eggert committed
209 210 211

  /* Compute intervening leap days correctly even if year is negative.
     Take care to avoid integer overflow here.  */
Paul Eggert's avatar
Paul Eggert committed
212 213
  int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
  int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
Paul Eggert's avatar
Paul Eggert committed
214 215
  int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
  int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
Paul Eggert's avatar
Paul Eggert committed
216 217
  int a400 = shr (a100, 2);
  int b400 = shr (b100, 2);
Paul Eggert's avatar
Paul Eggert committed
218 219
  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);

Paul Eggert's avatar
Paul Eggert committed
220 221 222 223 224 225
  /* Compute the desired time without overflowing.  */
  long_int years = year1 - year0;
  long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
  long_int hours = 24 * days + hour1 - hour0;
  long_int minutes = 60 * hours + min1 - min0;
  long_int seconds = 60 * minutes + sec1 - sec0;
Paul Eggert's avatar
Paul Eggert committed
226 227 228
  return seconds;
}

Paul Eggert's avatar
Paul Eggert committed
229 230 231 232
/* Return the average of A and B, even if A + B would overflow.
   Round toward positive infinity.  */
static long_int
long_int_avg (long_int a, long_int b)
233
{
Paul Eggert's avatar
Paul Eggert committed
234
  return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
235
}
Paul Eggert's avatar
Paul Eggert committed
236

Paul Eggert's avatar
Paul Eggert committed
237 238 239 240
/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC)
   minus *TP seconds, assuming no clock adjustments occurred between
   the two timestamps.

Paul Eggert's avatar
Paul Eggert committed
241 242
   YEAR and YDAY must not be so large that multiplying them by three times the
   number of seconds in a year (or day, respectively) would overflow long_int.
Paul Eggert's avatar
Paul Eggert committed
243
   *TP should be in the usual range.  */
Paul Eggert's avatar
Paul Eggert committed
244
static long_int
Paul Eggert's avatar
Paul Eggert committed
245 246
tm_diff (long_int year, long_int yday, int hour, int min, int sec,
	 struct tm const *tp)
Paul Eggert's avatar
Paul Eggert committed
247
{
Paul Eggert's avatar
Paul Eggert committed
248 249 250
  return ydhms_diff (year, yday, hour, min, sec,
		     tp->tm_year, tp->tm_yday,
		     tp->tm_hour, tp->tm_min, tp->tm_sec);
Paul Eggert's avatar
Paul Eggert committed
251 252 253
}

/* Use CONVERT to convert T to a struct tm value in *TM.  T must be in
Paul Eggert's avatar
Paul Eggert committed
254
   range for __time64_t.  Return TM if successful, NULL (setting errno) on
Paul Eggert's avatar
Paul Eggert committed
255
   failure.  */
Paul Eggert's avatar
Paul Eggert committed
256
static struct tm *
Paul Eggert's avatar
Paul Eggert committed
257
convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
Paul Eggert's avatar
Paul Eggert committed
258 259
	      long_int t, struct tm *tm)
{
Paul Eggert's avatar
Paul Eggert committed
260
  __time64_t x = t;
Paul Eggert's avatar
Paul Eggert committed
261
  return convert (&x, tm);
Paul Eggert's avatar
Paul Eggert committed
262 263 264 265
}

/* Use CONVERT to convert *T to a broken down time in *TP.
   If *T is out of range for conversion, adjust it so that
Paul Eggert's avatar
Paul Eggert committed
266
   it is the nearest in-range value and then convert that.
Paul Eggert's avatar
Paul Eggert committed
267
   A value is in range if it fits in both __time64_t and long_int.
Paul Eggert's avatar
Paul Eggert committed
268
   Return TP on success, NULL (setting errno) on failure.  */
Paul Eggert's avatar
Paul Eggert committed
269
static struct tm *
Paul Eggert's avatar
Paul Eggert committed
270
ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
Paul Eggert's avatar
Paul Eggert committed
271
		long_int *t, struct tm *tp)
Paul Eggert's avatar
Paul Eggert committed
272
{
Paul Eggert's avatar
Paul Eggert committed
273 274 275 276
  long_int t1 = (*t < mktime_min ? mktime_min
		 : *t <= mktime_max ? *t : mktime_max);
  struct tm *r = convert_time (convert, t1, tp);
  if (r)
Paul Eggert's avatar
Paul Eggert committed
277
    {
Paul Eggert's avatar
Paul Eggert committed
278 279 280 281 282
      *t = t1;
      return r;
    }
  if (errno != EOVERFLOW)
    return NULL;
Paul Eggert's avatar
Paul Eggert committed
283

Paul Eggert's avatar
Paul Eggert committed
284 285 286
  long_int bad = t1;
  long_int ok = 0;
  struct tm oktm; oktm.tm_sec = -1;
Paul Eggert's avatar
Paul Eggert committed
287

Paul Eggert's avatar
Paul Eggert committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301
  /* BAD is a known out-of-range value, and OK is a known in-range one.
     Use binary search to narrow the range between BAD and OK until
     they differ by 1.  */
  while (true)
    {
      long_int mid = long_int_avg (ok, bad);
      if (mid == ok || mid == bad)
	break;
      if (convert_time (convert, mid, tp))
	ok = mid, oktm = *tp;
      else if (errno != EOVERFLOW)
	return NULL;
      else
	bad = mid;
Paul Eggert's avatar
Paul Eggert committed
302 303
    }

Paul Eggert's avatar
Paul Eggert committed
304 305 306 307 308
  if (oktm.tm_sec < 0)
    return NULL;
  *t = ok;
  *tp = oktm;
  return tp;
Paul Eggert's avatar
Paul Eggert committed
309 310
}

Paul Eggert's avatar
Paul Eggert committed
311

Paul Eggert's avatar
Paul Eggert committed
312
/* Convert *TP to a __time64_t value, inverting
Paul Eggert's avatar
Paul Eggert committed
313 314 315 316
   the monotonic and mostly-unit-linear conversion function CONVERT.
   Use *OFFSET to keep track of a guess at the offset of the result,
   compared to what the result would be for UTC without leap seconds.
   If *OFFSET's guess is correct, only one CONVERT call is needed.
Paul Eggert's avatar
Paul Eggert committed
317 318
   If successful, set *TP to the canonicalized struct tm;
   otherwise leave *TP alone, return ((time_t) -1) and set errno.
Paul Eggert's avatar
Paul Eggert committed
319
   This function is external because it is used also by timegm.c.  */
Paul Eggert's avatar
Paul Eggert committed
320
__time64_t
Paul Eggert's avatar
Paul Eggert committed
321
__mktime_internal (struct tm *tp,
Paul Eggert's avatar
Paul Eggert committed
322
		   struct tm *(*convert) (const __time64_t *, struct tm *),
Paul Eggert's avatar
Paul Eggert committed
323
		   mktime_offset_t *offset)
Paul Eggert's avatar
Paul Eggert committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
{
  struct tm tm;

  /* The maximum number of probes (calls to CONVERT) should be enough
     to handle any combinations of time zone rule changes, solar time,
     leap seconds, and oscillations around a spring-forward gap.
     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
  int remaining_probes = 6;

  /* Time requested.  Copy it in case CONVERT modifies *TP; this can
     occur if TP is localtime's returned value and CONVERT is localtime.  */
  int sec = tp->tm_sec;
  int min = tp->tm_min;
  int hour = tp->tm_hour;
  int mday = tp->tm_mday;
  int mon = tp->tm_mon;
  int year_requested = tp->tm_year;
341
  int isdst = tp->tm_isdst;
Paul Eggert's avatar
Paul Eggert committed
342 343

  /* 1 if the previous probe was DST.  */
Paul Eggert's avatar
Paul Eggert committed
344
  int dst2 = 0;
Paul Eggert's avatar
Paul Eggert committed
345 346 347 348 349

  /* Ensure that mon is in range, and set year accordingly.  */
  int mon_remainder = mon % 12;
  int negative_mon_remainder = mon_remainder < 0;
  int mon_years = mon / 12 - negative_mon_remainder;
350 351
  long_int lyear_requested = year_requested;
  long_int year = lyear_requested + mon_years;
Paul Eggert's avatar
Paul Eggert committed
352 353

  /* The other values need not be in range:
Paul Eggert's avatar
Paul Eggert committed
354
     the remaining code handles overflows correctly.  */
Paul Eggert's avatar
Paul Eggert committed
355 356 357 358

  /* Calculate day of year from year, month, and day of month.
     The result need not be in range.  */
  int mon_yday = ((__mon_yday[leapyear (year)]
Paul Eggert's avatar
Paul Eggert committed
359 360
		   [mon_remainder + 12 * negative_mon_remainder])
		  - 1);
361 362
  long_int lmday = mday;
  long_int yday = mon_yday + lmday;
Paul Eggert's avatar
Paul Eggert committed
363

Paul Eggert's avatar
Paul Eggert committed
364
  mktime_offset_t off = *offset;
Paul Eggert's avatar
Paul Eggert committed
365
  int negative_offset_guess;
Paul Eggert's avatar
Paul Eggert committed
366 367 368 369 370 371

  int sec_requested = sec;

  if (LEAP_SECONDS_POSSIBLE)
    {
      /* Handle out-of-range seconds specially,
Paul Eggert's avatar
Paul Eggert committed
372
	 since ydhms_diff assumes every minute has 60 seconds.  */
Paul Eggert's avatar
Paul Eggert committed
373
      if (sec < 0)
Paul Eggert's avatar
Paul Eggert committed
374
	sec = 0;
Paul Eggert's avatar
Paul Eggert committed
375
      if (59 < sec)
Paul Eggert's avatar
Paul Eggert committed
376
	sec = 59;
Paul Eggert's avatar
Paul Eggert committed
377 378 379 380 381
    }

  /* Invert CONVERT by probing.  First assume the same offset as last
     time.  */

Paul Eggert's avatar
Paul Eggert committed
382
  INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
Paul Eggert's avatar
Paul Eggert committed
383 384 385 386
  long_int t0 = ydhms_diff (year, yday, hour, min, sec,
			    EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
			    negative_offset_guess);
  long_int t = t0, t1 = t0, t2 = t0;
Paul Eggert's avatar
Paul Eggert committed
387 388 389

  /* Repeatedly use the error to improve the guess.  */

Paul Eggert's avatar
Paul Eggert committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
  while (true)
    {
      if (! ranged_convert (convert, &t, &tm))
	return -1;
      long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
      if (dt == 0)
	break;

      if (t == t1 && t != t2
	  && (tm.tm_isdst < 0
	      || (isdst < 0
		  ? dst2 <= (tm.tm_isdst != 0)
		  : (isdst != 0) != (tm.tm_isdst != 0))))
	/* We can't possibly find a match, as we are oscillating
	   between two values.  The requested time probably falls
	   within a spring-forward gap of size DT.  Follow the common
	   practice in this case, which is to return a time that is DT
	   away from the requested time, preferring a time whose
	   tm_isdst differs from the requested value.  (If no tm_isdst
	   was requested and only one of the two values has a nonzero
	   tm_isdst, prefer that value.)  In practice, this is more
	   useful than returning -1.  */
	goto offset_found;

      remaining_probes--;
      if (remaining_probes == 0)
	{
	  __set_errno (EOVERFLOW);
	  return -1;
	}

      t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
    }
Paul Eggert's avatar
Paul Eggert committed
423 424 425

  /* We have a match.  Check whether tm.tm_isdst has the requested
     value, if any.  */
426
  if (isdst_differ (isdst, tm.tm_isdst))
Paul Eggert's avatar
Paul Eggert committed
427 428
    {
      /* tm.tm_isdst has the wrong value.  Look for a neighboring
Paul Eggert's avatar
Paul Eggert committed
429
	 time with the right value, and use its UTC offset.
Paul Eggert's avatar
Paul Eggert committed
430

Paul Eggert's avatar
Paul Eggert committed
431 432 433
	 Heuristic: probe the adjacent timestamps in both directions,
	 looking for the desired isdst.  This should work for all real
	 time zone histories in the tz database.  */
Paul Eggert's avatar
Paul Eggert committed
434 435

      /* Distance between probes when looking for a DST boundary.  In
Paul Eggert's avatar
Paul Eggert committed
436 437 438 439 440 441
	 tzdata2003a, the shortest period of DST is 601200 seconds
	 (e.g., America/Recife starting 2000-10-08 01:00), and the
	 shortest period of non-DST surrounded by DST is 694800
	 seconds (Africa/Tunis starting 1943-04-17 01:00).  Use the
	 minimum of these two values, so we don't miss these short
	 periods when probing.  */
Paul Eggert's avatar
Paul Eggert committed
442 443 444
      int stride = 601200;

      /* The longest period of DST in tzdata2003a is 536454000 seconds
Paul Eggert's avatar
Paul Eggert committed
445 446 447 448
	 (e.g., America/Jujuy starting 1946-10-01 01:00).  The longest
	 period of non-DST is much longer, but it makes no real sense
	 to search for more than a year of non-DST, so use the DST
	 max.  */
Paul Eggert's avatar
Paul Eggert committed
449 450 451
      int duration_max = 536454000;

      /* Search in both directions, so the maximum distance is half
Paul Eggert's avatar
Paul Eggert committed
452
	 the duration; add the stride to avoid off-by-1 problems.  */
Paul Eggert's avatar
Paul Eggert committed
453 454 455 456 457
      int delta_bound = duration_max / 2 + stride;

      int delta, direction;

      for (delta = stride; delta < delta_bound; delta += stride)
Paul Eggert's avatar
Paul Eggert committed
458
	for (direction = -1; direction <= 1; direction += 2)
Paul Eggert's avatar
Paul Eggert committed
459 460 461 462 463
	  {
	    long_int ot;
	    if (! INT_ADD_WRAPV (t, delta * direction, &ot))
	      {
		struct tm otm;
Paul Eggert's avatar
Paul Eggert committed
464 465
		if (! ranged_convert (convert, &ot, &otm))
		  return -1;
Paul Eggert's avatar
Paul Eggert committed
466 467 468 469
		if (! isdst_differ (isdst, otm.tm_isdst))
		  {
		    /* We found the desired tm_isdst.
		       Extrapolate back to the desired time.  */
Paul Eggert's avatar
Paul Eggert committed
470 471 472 473 474 475 476 477 478 479 480 481
		    long_int gt = ot + tm_diff (year, yday, hour, min, sec,
						&otm);
		    if (mktime_min <= gt && gt <= mktime_max)
		      {
			if (convert_time (convert, gt, &tm))
			  {
			    t = gt;
			    goto offset_found;
			  }
			if (errno != EOVERFLOW)
			  return -1;
		      }
Paul Eggert's avatar
Paul Eggert committed
482 483 484
		  }
	      }
	  }
Paul Eggert's avatar
Paul Eggert committed
485 486 487

      __set_errno (EOVERFLOW);
      return -1;
Paul Eggert's avatar
Paul Eggert committed
488 489 490
    }

 offset_found:
Paul Eggert's avatar
Paul Eggert committed
491 492 493
  /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS.
     This is just a heuristic to speed up the next mktime call, and
     correctness is unaffected if integer overflow occurs here.  */
Paul Eggert's avatar
Paul Eggert committed
494 495
  INT_SUBTRACT_WRAPV (t, t0, offset);
  INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset);
Paul Eggert's avatar
Paul Eggert committed
496 497 498 499

  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
    {
      /* Adjust time to reflect the tm_sec requested, not the normalized value.
Paul Eggert's avatar
Paul Eggert committed
500
	 Also, repair any damage from a false match due to a leap second.  */
Paul Eggert's avatar
Paul Eggert committed
501 502 503 504
      long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
      sec_adjustment -= sec;
      sec_adjustment += sec_requested;
      if (INT_ADD_WRAPV (t, sec_adjustment, &t)
Paul Eggert's avatar
Paul Eggert committed
505 506 507 508 509 510
	  || ! (mktime_min <= t && t <= mktime_max))
	{
	  __set_errno (EOVERFLOW);
	  return -1;
	}
      if (! convert_time (convert, t, &tm))
Paul Eggert's avatar
Paul Eggert committed
511
	return -1;
Paul Eggert's avatar
Paul Eggert committed
512 513 514 515 516 517
    }

  *tp = tm;
  return t;
}

Paul Eggert's avatar
Paul Eggert committed
518
#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */
Paul Eggert's avatar
Paul Eggert committed
519

Paul Eggert's avatar
Paul Eggert committed
520
#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
Paul Eggert's avatar
Paul Eggert committed
521

Paul Eggert's avatar
Paul Eggert committed
522 523 524
/* Convert *TP to a __time64_t value.  */
__time64_t
__mktime64 (struct tm *tp)
Paul Eggert's avatar
Paul Eggert committed
525 526
{
  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
Paul Eggert's avatar
Paul Eggert committed
527
     time zone names contained in the external variable 'tzname' shall
Paul Eggert's avatar
Paul Eggert committed
528 529 530
     be set as if the tzset() function had been called.  */
  __tzset ();

Paul Eggert's avatar
Paul Eggert committed
531
# if defined _LIBC || NEED_MKTIME_WORKING
Paul Eggert's avatar
Paul Eggert committed
532
  static mktime_offset_t localtime_offset;
Paul Eggert's avatar
Paul Eggert committed
533
  return __mktime_internal (tp, __localtime64_r, &localtime_offset);
Paul Eggert's avatar
Paul Eggert committed
534 535 536 537
# else
#  undef mktime
  return mktime (tp);
# endif
Paul Eggert's avatar
Paul Eggert committed
538
}
Paul Eggert's avatar
Paul Eggert committed
539
#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
Paul Eggert's avatar
Paul Eggert committed
540

Paul Eggert's avatar
Paul Eggert committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
#if defined _LIBC && __TIMESIZE != 64

libc_hidden_def (__mktime64)

time_t
mktime (struct tm *tp)
{
  struct tm tm = *tp;
  __time64_t t = __mktime64 (&tm);
  if (in_time_t_range (t))
    {
      *tp = tm;
      return t;
    }
  else
    {
      __set_errno (EOVERFLOW);
      return -1;
    }
}

Paul Eggert's avatar
Paul Eggert committed
562 563
#endif

Paul Eggert's avatar
Paul Eggert committed
564
weak_alias (mktime, timelocal)
Paul Eggert's avatar
Paul Eggert committed
565 566
libc_hidden_def (mktime)
libc_hidden_weak (timelocal)