@@ -247,12 +247,12 @@ extern int __gettimeofday64 (struct __timeval64 *restrict tv,
libc_hidden_proto (__gettimeofday64)
#endif
-/* 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 TP if successful, a null pointer otherwise. */
+/* Compute the 'struct tm' representation of T, offset OFFSET seconds
+ east of UTC and minus a leap second correction CORR.
+ If successful, store year, yday, mon, mday, wday, hour, min, sec
+ into *TP and return TP; otherwise return a null pointer. */
extern struct tm *__offtime (__time64_t __timer,
- long int __offset,
+ long int __offset, int __corr,
struct tm *__tp) attribute_hidden;
extern char *__asctime_r (const struct tm *__tp, char *__buf)
@@ -16,43 +16,28 @@
<https://www.gnu.org/licenses/>. */
#include <errno.h>
+#include <stdckdint.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 TP if successful, a null pointer otherwise. */
+/* Compute the 'struct tm' representation of T, offset OFFSET seconds
+ east of UTC and minus a leap second correction CORR.
+ If successful, store year, yday, mon, mday, wday, hour, min, sec
+ into *TP and return TP; otherwise return a null pointer. */
struct tm *
-__offtime (__time64_t t, long int offset, struct tm *tp)
+__offtime (__time64_t t, long int offset, int corr, struct tm *tp)
{
- __time64_t days, rem, y;
- const unsigned short int *ip;
+ int rem = (t % SECS_PER_DAY + offset % SECS_PER_DAY - corr % SECS_PER_DAY
+ + 3 * SECS_PER_DAY);
+ __time64_t days = (t / SECS_PER_DAY + offset / SECS_PER_DAY
+ - corr / SECS_PER_DAY + rem / SECS_PER_DAY - 3);
- 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;
+ int wday_rem = (4 + days) % 7;
+
+ __time64_t 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))
@@ -68,19 +53,28 @@ __offtime (__time64_t t, long int offset, struct tm *tp)
- LEAPS_THRU_END_OF (y - 1));
y = yg;
}
- tp->tm_year = y - 1900;
- if (tp->tm_year != y - 1900)
+ int year;
+ if (ckd_sub (&year, y, 1900))
{
/* The year cannot be represented due to overflow. */
__set_errno (EOVERFLOW);
return NULL;
}
+
+ int day_rem = rem % SECS_PER_DAY;
+ tp->tm_hour = day_rem / SECS_PER_HOUR;
+ int hour_rem = day_rem % SECS_PER_HOUR;
+ tp->tm_sec = hour_rem % 60;
+ tp->tm_min = hour_rem / 60;
+ tp->tm_year = year;
+ tp->tm_wday = wday_rem + (wday_rem < 0 ? 7 : 0);
tp->tm_yday = days;
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
+ unsigned short int yday = days;
+ unsigned short int const *ip = __mon_yday[__isleap (y)];
+ int mon;
+ for (mon = 11; yday < ip[mon]; mon--)
continue;
- days -= ip[y];
- tp->tm_mon = y;
- tp->tm_mday = days + 1;
+ tp->tm_mon = mon;
+ tp->tm_mday = yday - ip[mon] + 1;
return tp;
}
@@ -648,7 +648,7 @@ __tzfile_compute (__time64_t timer, int use_localtime,
/* Convert to broken down structure. If this fails do not
use the string. */
- if (__glibc_unlikely (__offtime (timer, 0, tp) == NULL))
+ if (__glibc_unlikely (__offtime (timer, 0, 0, tp) == NULL))
goto use_last;
/* Use the rules from the TZ string to compute the change. */
@@ -610,7 +610,7 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)
&leap_extra_sec, tp);
else
{
- tp = __offtime (timer, 0, tp);
+ tp = __offtime (timer, 0, 0, tp);
if (tp && use_localtime)
__tz_compute (timer, tp);
leap_correction = 0;
@@ -626,7 +626,7 @@ __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)
tp->tm_gmtoff = 0L;
}
- if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp) != NULL)
+ if (__offtime (timer, tp->tm_gmtoff, leap_correction, tp) != NULL)
{
/* This assumes leap seconds can occur only when the local
time offset from UTC is a multiple of 60 seconds,