diff options
Diffstat (limited to 'REORG.TODO/time/offtime.c')
-rw-r--r-- | REORG.TODO/time/offtime.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/REORG.TODO/time/offtime.c b/REORG.TODO/time/offtime.c new file mode 100644 index 0000000000..75a28fed84 --- /dev/null +++ b/REORG.TODO/time/offtime.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> + +#define SECS_PER_HOUR (60 * 60) +#define SECS_PER_DAY (SECS_PER_HOUR * 24) + +/* Compute the `struct tm' representation of *T, + offset OFFSET seconds east of UTC, + and store year, yday, mon, mday, wday, hour, min, sec into *TP. + Return nonzero if successful. */ +int +__offtime (const time_t *t, long int offset, struct tm *tp) +{ + time_t days, rem, y; + const unsigned short int *ip; + + days = *t / SECS_PER_DAY; + rem = *t % SECS_PER_DAY; + rem += offset; + while (rem < 0) + { + rem += SECS_PER_DAY; + --days; + } + while (rem >= SECS_PER_DAY) + { + rem -= SECS_PER_DAY; + ++days; + } + tp->tm_hour = rem / SECS_PER_HOUR; + rem %= SECS_PER_HOUR; + tp->tm_min = rem / 60; + tp->tm_sec = rem % 60; + /* January 1, 1970 was a Thursday. */ + tp->tm_wday = (4 + days) % 7; + if (tp->tm_wday < 0) + tp->tm_wday += 7; + y = 1970; + +#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) +#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) + + while (days < 0 || days >= (__isleap (y) ? 366 : 365)) + { + /* Guess a corrected year, assuming 365 days per year. */ + time_t yg = y + days / 365 - (days % 365 < 0); + + /* Adjust DAYS and Y to match the guessed year. */ + days -= ((yg - y) * 365 + + LEAPS_THRU_END_OF (yg - 1) + - LEAPS_THRU_END_OF (y - 1)); + y = yg; + } + tp->tm_year = y - 1900; + if (tp->tm_year != y - 1900) + { + /* The year cannot be represented due to overflow. */ + __set_errno (EOVERFLOW); + return 0; + } + tp->tm_yday = days; + ip = __mon_yday[__isleap(y)]; + for (y = 11; days < (long int) ip[y]; --y) + continue; + days -= ip[y]; + tp->tm_mon = y; + tp->tm_mday = days + 1; + return 1; +} |