root/lib/mktime.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. my_tzset
  2. shr
  3. leapyear
  4. isdst_differ
  5. ydhms_diff
  6. long_int_avg
  7. tm_diff
  8. convert_time
  9. ranged_convert
  10. __mktime_internal
  11. __mktime64
  12. libc_hidden_def

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

/* [<][>][^][v][top][bottom][index][help] */