(root)/
glibc-2.38/
time/
offtime.c
       1  /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <time.h>
      20  
      21  #define	SECS_PER_HOUR	(60 * 60)
      22  #define	SECS_PER_DAY	(SECS_PER_HOUR * 24)
      23  
      24  /* Compute the `struct tm' representation of T,
      25     offset OFFSET seconds east of UTC,
      26     and store year, yday, mon, mday, wday, hour, min, sec into *TP.
      27     Return nonzero if successful.  */
      28  int
      29  __offtime (__time64_t t, long int offset, struct tm *tp)
      30  {
      31    __time64_t days, rem, y;
      32    const unsigned short int *ip;
      33  
      34    days = t / SECS_PER_DAY;
      35    rem = t % SECS_PER_DAY;
      36    rem += offset;
      37    while (rem < 0)
      38      {
      39        rem += SECS_PER_DAY;
      40        --days;
      41      }
      42    while (rem >= SECS_PER_DAY)
      43      {
      44        rem -= SECS_PER_DAY;
      45        ++days;
      46      }
      47    tp->tm_hour = rem / SECS_PER_HOUR;
      48    rem %= SECS_PER_HOUR;
      49    tp->tm_min = rem / 60;
      50    tp->tm_sec = rem % 60;
      51    /* January 1, 1970 was a Thursday.  */
      52    tp->tm_wday = (4 + days) % 7;
      53    if (tp->tm_wday < 0)
      54      tp->tm_wday += 7;
      55    y = 1970;
      56  
      57  #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
      58  #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
      59  
      60    while (days < 0 || days >= (__isleap (y) ? 366 : 365))
      61      {
      62        /* Guess a corrected year, assuming 365 days per year.  */
      63        __time64_t yg = y + days / 365 - (days % 365 < 0);
      64  
      65        /* Adjust DAYS and Y to match the guessed year.  */
      66        days -= ((yg - y) * 365
      67  	       + LEAPS_THRU_END_OF (yg - 1)
      68  	       - LEAPS_THRU_END_OF (y - 1));
      69        y = yg;
      70      }
      71    tp->tm_year = y - 1900;
      72    if (tp->tm_year != y - 1900)
      73      {
      74        /* The year cannot be represented due to overflow.  */
      75        __set_errno (EOVERFLOW);
      76        return 0;
      77      }
      78    tp->tm_yday = days;
      79    ip = __mon_yday[__isleap(y)];
      80    for (y = 11; days < (long int) ip[y]; --y)
      81      continue;
      82    days -= ip[y];
      83    tp->tm_mon = y;
      84    tp->tm_mday = days + 1;
      85    return 1;
      86  }