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

Karl Berry's avatar
Karl Berry committed
6 7 8 9
   This program 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 2, or (at your option)
   any later version.
Jim Meyering's avatar
Jim Meyering committed
10

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

Karl Berry's avatar
Karl Berry committed
16 17
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation,
Karl Berry's avatar
Karl Berry committed
18
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
Jim Meyering's avatar
Jim Meyering committed
19

Jim Meyering's avatar
Jim Meyering committed
20 21
/* Define this to have a standalone program to test this implementation of
   mktime.  */
Jim Meyering's avatar
Jim Meyering committed
22
/* #define DEBUG 1 */
Jim Meyering's avatar
Jim Meyering committed
23

24
#ifndef _LIBC
Jim Meyering's avatar
Jim Meyering committed
25
# include <config.h>
Jim Meyering's avatar
Jim Meyering committed
26 27
#endif

Jim Meyering's avatar
Jim Meyering committed
28 29 30 31
/* Assume that leap seconds are possible, unless told otherwise.
   If the host has a `zic' command with a `-L leapsecondfilename' option,
   then it supports leap seconds; otherwise it probably doesn't.  */
#ifndef LEAP_SECONDS_POSSIBLE
Jim Meyering's avatar
Jim Meyering committed
32
# define LEAP_SECONDS_POSSIBLE 1
Jim Meyering's avatar
Jim Meyering committed
33 34
#endif

Jim Meyering's avatar
Jim Meyering committed
35 36
#include <time.h>

37
#include <limits.h>
Jim Meyering's avatar
Jim Meyering committed
38

39
#include <string.h>             /* For the real memcpy prototype.  */
40

Jim Meyering's avatar
Jim Meyering committed
41
#if DEBUG
Jim Meyering's avatar
Jim Meyering committed
42
# include <stdio.h>
Paul Eggert's avatar
Paul Eggert committed
43
# include <stdlib.h>
Jim Meyering's avatar
Jim Meyering committed
44
/* Make it work even if the system's libc has its own mktime routine.  */
Jim Meyering's avatar
Jim Meyering committed
45
# define mktime my_mktime
Jim Meyering's avatar
Jim Meyering committed
46
#endif /* DEBUG */
Jim Meyering's avatar
Jim Meyering committed
47

48 49 50 51 52 53 54 55 56 57
/* Shift A right by B bits portably, by dividing A by 2**B and
   truncating towards minus infinity.  A and B should be free of side
   effects, and B should be in the range 0 <= B <= INT_BITS - 2, where
   INT_BITS is the number of useful bits in an int.  GNU code can
   assume that INT_BITS is at least 32.

   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.  */
58 59 60
#define SHR(a, b)       \
  (-1 >> 1 == -1        \
   ? (a) >> (b)         \
61 62
   : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))

63 64 65 66 67 68 69
/* The extra casts in the following macros work around compiler bugs,
   e.g., in Cray C 5.0.3.0.  */

/* True if the arithmetic type T is an integer type.  bool counts as
   an integer.  */
#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1)

70 71 72
/* True if negative values of the signed integer type T use two's
   complement, ones' complement, or signed magnitude representation,
   respectively.  Much GNU code assumes two's complement, but some
73 74 75 76
   people like to be portable to all possible C hosts.  */
#define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1)
#define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0)
#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 83 84 85 86
   macros have undefined behavior if T is signed and has padding bits.
   If this is a problem for you, please let us know how to fix it for
   your host.  */
#define TYPE_MINIMUM(t) \
  ((t) (! TYPE_SIGNED (t) \
87 88 89 90
        ? (t) 0 \
        : TYPE_SIGNED_MAGNITUDE (t) \
        ? ~ (t) 0 \
        : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
91 92
#define TYPE_MAXIMUM(t) \
  ((t) (! TYPE_SIGNED (t) \
93 94
        ? (t) -1 \
        : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
95

Jim Meyering's avatar
Jim Meyering committed
96
#ifndef TIME_T_MIN
97
# define TIME_T_MIN TYPE_MINIMUM (time_t)
Jim Meyering's avatar
Jim Meyering committed
98 99
#endif
#ifndef TIME_T_MAX
100
# define TIME_T_MAX TYPE_MAXIMUM (time_t)
Jim Meyering's avatar
Jim Meyering committed
101
#endif
102
#define TIME_T_MIDPOINT (SHR (TIME_T_MIN + TIME_T_MAX, 1) + 1)
103 104 105 106

/* Verify a requirement at compile-time (unlike assert, which is runtime).  */
#define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }

107 108
verify (time_t_is_integer, TYPE_IS_INTEGER (time_t));
verify (twos_complement_arithmetic, TYPE_TWOS_COMPLEMENT (int));
109 110 111
/* The code also assumes that signed integer overflow silently wraps
   around, but this assumption can't be stated without causing a
   diagnostic on some hosts.  */
Jim Meyering's avatar
Jim Meyering committed
112

Jim Meyering's avatar
Jim Meyering committed
113
#define EPOCH_YEAR 1970
114 115
#define TM_YEAR_BASE 1900
verify (base_year_is_a_multiple_of_100, TM_YEAR_BASE % 100 == 0);
Jim Meyering's avatar
Jim Meyering committed
116

117 118
/* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
static inline int
119
leapyear (long int year)
120 121 122 123 124 125
{
  /* 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
126
         || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
127
}
Jim Meyering's avatar
Jim Meyering committed
128

Jim Meyering's avatar
Jim Meyering committed
129
/* How many days come before each month (0-12).  */
130 131 132 133
#ifndef _LIBC
static
#endif
const unsigned short int __mon_yday[2][13] =
Jim Meyering's avatar
Jim Meyering committed
134 135 136 137 138 139
  {
    /* 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 }
  };
Jim Meyering's avatar
Jim Meyering committed
140

Jim Meyering's avatar
Jim Meyering committed
141

142
#ifndef _LIBC
143
/* Portable standalone applications should supply a <time.h> that
144 145 146 147 148
   declares a POSIX-compliant localtime_r, for the benefit of older
   implementations that lack localtime_r or have a nonstandard one.
   See the gnulib time_r module for one way to implement this.  */
# undef __localtime_r
# define __localtime_r localtime_r
149
# define __mktime_internal mktime_internal
150
# include "mktime-internal.h"
151
#endif
Jim Meyering's avatar
Jim Meyering committed
152

153 154 155
/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) -
   (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks
   were not adjusted between the time stamps.
Jim Meyering's avatar
Jim Meyering committed
156

157 158 159 160 161 162 163 164 165
   The YEAR values uses the same numbering as TP->tm_year.  Values
   need not be in the usual range.  However, YEAR1 must not be less
   than 2 * INT_MIN or greater than 2 * INT_MAX.

   The result may overflow.  It is the caller's responsibility to
   detect overflow.  */

static inline time_t
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 170
#if 0 /* This assertion fails on 32-bit systems with 64-bit time_t, such as
         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 176

  /* Compute intervening leap days correctly even if year is negative.
     Take care to avoid integer overflow here.  */
177 178
  int a4 = SHR (year1, 2) + SHR (TM_YEAR_BASE, 2) - ! (year1 & 3);
  int b4 = SHR (year0, 2) + SHR (TM_YEAR_BASE, 2) - ! (year0 & 3);
179 180
  int a100 = a4 / 25 - (a4 % 25 < 0);
  int b100 = b4 / 25 - (b4 % 25 < 0);
181 182
  int a400 = SHR (a100, 2);
  int b400 = SHR (b100, 2);
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
  int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);

  /* Compute the desired time in time_t precision.  Overflow might
     occur here.  */
  time_t tyear1 = year1;
  time_t years = tyear1 - year0;
  time_t days = 365 * years + yday1 - yday0 + intervening_leap_days;
  time_t hours = 24 * days + hour1 - hour0;
  time_t minutes = 60 * hours + min1 - min0;
  time_t seconds = 60 * minutes + sec1 - sec0;
  return seconds;
}


/* Return a time_t value corresponding to (YEAR-YDAY HOUR:MIN:SEC),
   assuming that *T corresponds to *TP and that no clock adjustments
   occurred between *TP and the desired time.
   If TP is null, return a value not equal to *T; this avoids false matches.
   If overflow occurs, yield the minimal or maximal value, except do not
   yield a value equal to *T.  */
Jim Meyering's avatar
Jim Meyering committed
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)
Jim Meyering's avatar
Jim Meyering committed
206
{
207
  if (tp)
Jim Meyering's avatar
Jim Meyering committed
208
    {
209
      time_t d = ydhms_diff (year, yday, hour, min, sec,
210 211
                             tp->tm_year, tp->tm_yday,
                             tp->tm_hour, tp->tm_min, tp->tm_sec);
212 213
      time_t t1 = *t + d;
      if ((t1 < *t) == (TYPE_SIGNED (time_t) ? d < 0 : TIME_T_MAX / 2 < d))
214
        return t1;
Jim Meyering's avatar
Jim Meyering committed
215
    }
216 217 218 219

  /* Overflow occurred one way or another.  Return the nearest result
     that is actually in range, except don't report a zero difference
     if the actual difference is nonzero, as that would cause a false
220 221
     match; and don't oscillate between two values, as that would
     confuse the spring-forward gap detector.  */
222
  return (*t < TIME_T_MIDPOINT
223 224
          ? (*t <= TIME_T_MIN + 1 ? *t + 1 : TIME_T_MIN)
          : (TIME_T_MAX - 1 <= *t ? *t - 1 : TIME_T_MAX));
Jim Meyering's avatar
Jim Meyering committed
225 226
}

Jim Meyering's avatar
Jim Meyering committed
227 228 229 230
/* Use CONVERT to convert *T to a broken down time in *TP.
   If *T is out of range for conversion, adjust it so that
   it is the nearest in-range value and then convert that.  */
static struct tm *
Jim Meyering's avatar
Jim Meyering committed
231
ranged_convert (struct tm *(*convert) (const time_t *, struct tm *),
232
                time_t *t, struct tm *tp)
Jim Meyering's avatar
Jim Meyering committed
233
{
234
  struct tm *r = convert (t, tp);
Jim Meyering's avatar
Jim Meyering committed
235

236
  if (!r && *t)
Jim Meyering's avatar
Jim Meyering committed
237 238 239 240 241
    {
      time_t bad = *t;
      time_t ok = 0;

      /* BAD is a known unconvertible time_t, and OK is a known good one.
242 243
         Use binary search to narrow the range between BAD and OK until
         they differ by 1.  */
Jim Meyering's avatar
Jim Meyering committed
244
      while (bad != ok + (bad < 0 ? -1 : 1))
245 246 247 248 249 250 251 252 253 254
        {
          time_t mid = *t = (bad < 0
                             ? bad + ((ok - bad) >> 1)
                             : ok + ((bad - ok) >> 1));
          r = convert (t, tp);
          if (r)
            ok = mid;
          else
            bad = mid;
        }
Jim Meyering's avatar
Jim Meyering committed
255 256

      if (!r && ok)
257 258 259 260 261 262
        {
          /* The last conversion attempt failed;
             revert to the most recent successful attempt.  */
          *t = ok;
          r = convert (t, tp);
        }
Jim Meyering's avatar
Jim Meyering committed
263 264 265 266 267 268
    }

  return r;
}


Jim Meyering's avatar
Jim Meyering committed
269 270 271 272
/* Convert *TP to a time_t value, inverting
   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.
273 274
   If *OFFSET's guess is correct, only one CONVERT call is needed.
   This function is external because it is used also by timegm.c.  */
275
time_t
Jim Meyering's avatar
Jim Meyering committed
276
__mktime_internal (struct tm *tp,
277 278
                   struct tm *(*convert) (const time_t *, struct tm *),
                   time_t *offset)
Jim Meyering's avatar
Jim Meyering committed
279
{
280
  time_t t, gt, t0, t1, t2;
Jim Meyering's avatar
Jim Meyering committed
281 282 283 284
  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,
285 286 287
     leap seconds, and oscillations around a spring-forward gap.
     POSIX.1 prohibits leap seconds, but some hosts have them anyway.  */
  int remaining_probes = 6;
Jim Meyering's avatar
Jim Meyering committed
288 289 290 291 292 293 294 295 296

  /* 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;
297 298
  /* Normalize the value.  */
  int isdst = ((tp->tm_isdst >> (8 * sizeof (tp->tm_isdst) - 1))
299
               | (tp->tm_isdst != 0));
Jim Meyering's avatar
Jim Meyering committed
300

301 302 303
  /* 1 if the previous probe was DST.  */
  int dst2;

Jim Meyering's avatar
Jim Meyering committed
304 305 306 307
  /* 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;
308 309
  long int lyear_requested = year_requested;
  long int year = lyear_requested + mon_years;
Jim Meyering's avatar
Jim Meyering committed
310 311 312 313 314 315 316 317

  /* The other values need not be in range:
     the remaining code handles minor overflows correctly,
     assuming int and time_t arithmetic wraps around.
     Major overflows are caught at the end.  */

  /* Calculate day of year from year, month, and day of month.
     The result need not be in range.  */
318
  int mon_yday = ((__mon_yday[leapyear (year)]
319 320
                   [mon_remainder + 12 * negative_mon_remainder])
                  - 1);
321 322 323 324
  long int lmday = mday;
  long int yday = mon_yday + lmday;

  time_t guessed_offset = *offset;
Jim Meyering's avatar
Jim Meyering committed
325

326
  int sec_requested = sec;
327

328 329 330
  if (LEAP_SECONDS_POSSIBLE)
    {
      /* 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 339
    }

  /* Invert CONVERT by probing.  First assume the same offset as last
     time.  */
Jim Meyering's avatar
Jim Meyering committed
340

341
  t0 = ydhms_diff (year, yday, hour, min, sec,
342
                   EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - guessed_offset);
343 344 345 346

  if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
    {
      /* time_t isn't large enough to rule out overflows, so check
347 348 349 350
         for major overflows.  A gross check suffices, since if t0
         has overflowed, it is off by a multiple of TIME_T_MAX -
         TIME_T_MIN + 1.  So ignore any component of the difference
         that is bounded by a small value.  */
351 352

      /* Approximate log base 2 of the number of time units per
353 354 355 356 357
         biennium.  A biennium is 2 years; use this unit instead of
         years to avoid integer overflow.  For example, 2 average
         Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
         which is 63113904 seconds, and rint (log2 (63113904)) is
         26.  */
358 359 360 361 362 363 364
      int ALOG2_SECONDS_PER_BIENNIUM = 26;
      int ALOG2_MINUTES_PER_BIENNIUM = 20;
      int ALOG2_HOURS_PER_BIENNIUM = 14;
      int ALOG2_DAYS_PER_BIENNIUM = 10;
      int LOG2_YEARS_PER_BIENNIUM = 1;

      int approx_requested_biennia =
365 366 367 368 369 370 371 372
        (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
         - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
         + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
         + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
         + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
         + (LEAP_SECONDS_POSSIBLE
            ? 0
            : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
373 374

      int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
375 376 377 378
      int diff = approx_biennia - approx_requested_biennia;
      int abs_diff = diff < 0 ? - diff : diff;

      /* IRIX 4.0.5 cc miscaculates TIME_T_MIN / 3: it erroneously
379 380 381
         gives a positive value of 715827882.  Setting a variable
         first then doing math on it seems to work.
         (ghazi@caip.rutgers.edu) */
382 383 384
      time_t time_t_max = TIME_T_MAX;
      time_t time_t_min = TIME_T_MIN;
      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 390 391 392 393 394 395 396 397 398 399
        {
          /* Overflow occurred.  Try repairing it; this might work if
             the time zone offset is enough to undo the overflow.  */
          time_t repaired_t0 = -1 - t0;
          approx_biennia = SHR (repaired_t0, ALOG2_SECONDS_PER_BIENNIUM);
          diff = approx_biennia - approx_requested_biennia;
          abs_diff = diff < 0 ? - diff : diff;
          if (overflow_threshold < abs_diff)
            return -1;
          guessed_offset += repaired_t0 - t0;
          t0 = repaired_t0;
        }
400
    }
Jim Meyering's avatar
Jim Meyering committed
401

402
  /* Repeatedly use the error to improve the guess.  */
Jim Meyering's avatar
Jim Meyering committed
403

404 405
  for (t = t1 = t2 = t0, dst2 = 0;
       (gt = guess_time_tm (year, yday, hour, min, sec, &t,
406 407
                            ranged_convert (convert, &t, &tm)),
        t != gt);
408
       t1 = t2, t2 = t, t = gt, dst2 = tm.tm_isdst != 0)
409
    if (t == t1 && t != t2
410 411 412 413
        && (tm.tm_isdst < 0
            || (isdst < 0
                ? dst2 <= (tm.tm_isdst != 0)
                : (isdst != 0) != (tm.tm_isdst != 0))))
414
      /* We can't possibly find a match, as we are oscillating
415 416 417 418 419 420 421 422
         between two values.  The requested time probably falls
         within a spring-forward gap of size GT - T.  Follow the common
         practice in this case, which is to return a time that is GT - T
         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.  */
423
      goto offset_found;
424
    else if (--remaining_probes == 0)
Jim Meyering's avatar
Jim Meyering committed
425
      return -1;
Jim Meyering's avatar
Jim Meyering committed
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)
Jim Meyering's avatar
Jim Meyering committed
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 435 436
         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.  */
437 438

      /* Distance between probes when looking for a DST boundary.  In
439 440 441 442 443 444
         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.  */
445 446 447
      int stride = 601200;

      /* The longest period of DST in tzdata2003a is 536454000 seconds
448 449 450 451
         (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.  */
452 453 454
      int duration_max = 536454000;

      /* Search in both directions, so the maximum distance is half
455
         the duration; add the stride to avoid off-by-1 problems.  */
456 457 458 459 460
      int delta_bound = duration_max / 2 + stride;

      int delta, direction;

      for (delta = stride; delta < delta_bound; delta += stride)
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
        for (direction = -1; direction <= 1; direction += 2)
          {
            time_t ot = t + delta * direction;
            if ((ot < t) == (direction < 0))
              {
                struct tm otm;
                ranged_convert (convert, &ot, &otm);
                if (otm.tm_isdst == isdst)
                  {
                    /* We found the desired tm_isdst.
                       Extrapolate back to the desired time.  */
                    t = guess_time_tm (year, yday, hour, min, sec, &ot, &otm);
                    ranged_convert (convert, &t, &tm);
                    goto offset_found;
                  }
              }
          }
Jim Meyering's avatar
Jim Meyering committed
478
    }
Jim Meyering's avatar
Jim Meyering committed
479

480 481
 offset_found:
  *offset = guessed_offset + t - t0;
Jim Meyering's avatar
Jim Meyering committed
482

483
  if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
Jim Meyering's avatar
Jim Meyering committed
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 488 489 490
      int sec_adjustment = (sec == 0 && tm.tm_sec == 60) - sec;
      t1 = t + sec_requested;
      t2 = t1 + sec_adjustment;
      if (((t1 < t) != (sec_requested < 0))
491 492 493
          | ((t2 < t1) != (sec_adjustment < 0))
          | ! convert (&t2, &tm))
        return -1;
494
      t = t2;
Jim Meyering's avatar
Jim Meyering committed
495
    }
Jim Meyering's avatar
Jim Meyering committed
496

Jim Meyering's avatar
Jim Meyering committed
497 498 499
  *tp = tm;
  return t;
}
Jim Meyering's avatar
Jim Meyering committed
500

Jim Meyering's avatar
Jim Meyering committed
501

502 503 504 505 506
/* FIXME: This should use a signed type wide enough to hold any UTC
   offset in seconds.  'int' should be good enough for GNU code.  We
   can't fix this unilaterally though, as other modules invoke
   __mktime_internal.  */
static time_t localtime_offset;
Jim Meyering's avatar
Jim Meyering committed
507 508 509

/* Convert *TP to a time_t value.  */
time_t
510
mktime (struct tm *tp)
Jim Meyering's avatar
Jim Meyering committed
511 512 513 514 515 516 517 518
{
#ifdef _LIBC
  /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
     time zone names contained in the external variable `tzname' shall
     be set as if the tzset() function had been called.  */
  __tzset ();
#endif

519
  return __mktime_internal (tp, __localtime_r, &localtime_offset);
Jim Meyering's avatar
Jim Meyering committed
520 521
}

Jim Meyering's avatar
Jim Meyering committed
522 523 524
#ifdef weak_alias
weak_alias (mktime, timelocal)
#endif
525 526 527 528 529

#ifdef _LIBC
libc_hidden_def (mktime)
libc_hidden_weak (timelocal)
#endif
Jim Meyering's avatar
Jim Meyering committed
530 531

#if DEBUG
Jim Meyering's avatar
Jim Meyering committed
532

Jim Meyering's avatar
Jim Meyering committed
533
static int
534
not_equal_tm (const struct tm *a, const struct tm *b)
Jim Meyering's avatar
Jim Meyering committed
535 536
{
  return ((a->tm_sec ^ b->tm_sec)
537 538 539 540 541 542 543
          | (a->tm_min ^ b->tm_min)
          | (a->tm_hour ^ b->tm_hour)
          | (a->tm_mday ^ b->tm_mday)
          | (a->tm_mon ^ b->tm_mon)
          | (a->tm_year ^ b->tm_year)
          | (a->tm_yday ^ b->tm_yday)
          | (a->tm_isdst ^ b->tm_isdst));
Jim Meyering's avatar
Jim Meyering committed
544
}
Jim Meyering's avatar
Jim Meyering committed
545

Jim Meyering's avatar
Jim Meyering committed
546
static void
547
print_tm (const struct tm *tp)
Jim Meyering's avatar
Jim Meyering committed
548
{
Jim Meyering's avatar
Jim Meyering committed
549 550
  if (tp)
    printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
551 552 553
            tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
            tp->tm_hour, tp->tm_min, tp->tm_sec,
            tp->tm_yday, tp->tm_wday, tp->tm_isdst);
Jim Meyering's avatar
Jim Meyering committed
554 555
  else
    printf ("0");
Jim Meyering's avatar
Jim Meyering committed
556 557
}

Jim Meyering's avatar
Jim Meyering committed
558
static int
559
check_result (time_t tk, struct tm tmk, time_t tl, const struct tm *lt)
Jim Meyering's avatar
Jim Meyering committed
560
{
Jim Meyering's avatar
Jim Meyering committed
561
  if (tk != tl || !lt || not_equal_tm (&tmk, lt))
Jim Meyering's avatar
Jim Meyering committed
562 563
    {
      printf ("mktime (");
Jim Meyering's avatar
Jim Meyering committed
564
      print_tm (lt);
565 566 567
      printf (")\nyields (");
      print_tm (&tmk);
      printf (") == %ld, should be %ld\n", (long int) tk, (long int) tl);
Jim Meyering's avatar
Jim Meyering committed
568 569 570 571
      return 1;
    }

  return 0;
Jim Meyering's avatar
Jim Meyering committed
572
}
Jim Meyering's avatar
Jim Meyering committed
573 574

int
575
main (int argc, char **argv)
Jim Meyering's avatar
Jim Meyering committed
576
{
Jim Meyering's avatar
Jim Meyering committed
577 578
  int status = 0;
  struct tm tm, tmk, tml;
Jim Meyering's avatar
Jim Meyering committed
579
  struct tm *lt;
580
  time_t tk, tl, tl1;
Jim Meyering's avatar
Jim Meyering committed
581 582 583 584
  char trailer;

  if ((argc == 3 || argc == 4)
      && (sscanf (argv[1], "%d-%d-%d%c",
585 586
                  &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
          == 3)
Jim Meyering's avatar
Jim Meyering committed
587
      && (sscanf (argv[2], "%d:%d:%d%c",
588 589
                  &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
          == 3))
Jim Meyering's avatar
Jim Meyering committed
590
    {
Jim Meyering's avatar
Jim Meyering committed
591 592 593 594 595
      tm.tm_year -= TM_YEAR_BASE;
      tm.tm_mon--;
      tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
      tmk = tm;
      tl = mktime (&tmk);
Jim Meyering's avatar
Jim Meyering committed
596 597
      lt = localtime (&tl);
      if (lt)
598 599 600 601
        {
          tml = *lt;
          lt = &tml;
        }
602
      printf ("mktime returns %ld == ", (long int) tl);
Jim Meyering's avatar
Jim Meyering committed
603 604
      print_tm (&tmk);
      printf ("\n");
Jim Meyering's avatar
Jim Meyering committed
605
      status = check_result (tl, tmk, tl, lt);
Jim Meyering's avatar
Jim Meyering committed
606
    }
Jim Meyering's avatar
Jim Meyering committed
607
  else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
Jim Meyering's avatar
Jim Meyering committed
608
    {
Jim Meyering's avatar
Jim Meyering committed
609 610 611
      time_t from = atol (argv[1]);
      time_t by = atol (argv[2]);
      time_t to = atol (argv[3]);
Jim Meyering's avatar
Jim Meyering committed
612

Jim Meyering's avatar
Jim Meyering committed
613
      if (argc == 4)
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
        for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
          {
            lt = localtime (&tl);
            if (lt)
              {
                tmk = tml = *lt;
                tk = mktime (&tmk);
                status |= check_result (tk, tmk, tl, &tml);
              }
            else
              {
                printf ("localtime (%ld) yields 0\n", (long int) tl);
                status = 1;
              }
            tl1 = tl + by;
            if ((tl1 < tl) != (by < 0))
              break;
          }
Jim Meyering's avatar
Jim Meyering committed
632
      else
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
        for (tl = from; by < 0 ? to <= tl : tl <= to; tl = tl1)
          {
            /* Null benchmark.  */
            lt = localtime (&tl);
            if (lt)
              {
                tmk = tml = *lt;
                tk = tl;
                status |= check_result (tk, tmk, tl, &tml);
              }
            else
              {
                printf ("localtime (%ld) yields 0\n", (long int) tl);
                status = 1;
              }
            tl1 = tl + by;
            if ((tl1 < tl) != (by < 0))
              break;
          }
Jim Meyering's avatar
Jim Meyering committed
652 653 654 655 656 657
    }
  else
    printf ("Usage:\
\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
658
            argv[0], argv[0], argv[0]);
Jim Meyering's avatar
Jim Meyering committed
659 660

  return status;
Jim Meyering's avatar
Jim Meyering committed
661
}
Jim Meyering's avatar
Jim Meyering committed
662

Jim Meyering's avatar
Jim Meyering committed
663
#endif /* DEBUG */
Jim Meyering's avatar
Jim Meyering committed
664 665 666

/*
Local Variables:
Paul Eggert's avatar
Paul Eggert committed
667
compile-command: "gcc -DDEBUG -Wall -W -O -g mktime.c -o mktime"
Jim Meyering's avatar
Jim Meyering committed
668 669
End:
*/