From 153bcd9bd3b337120e1afc75ce63cb5b80730913 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 8 Mar 2019 20:22:03 +0000 Subject: bugfix: leap second table. Also add leapsec reporting in localtm. --- doc/libstddjb/djbtime.html | 6 ++-- src/libstddjb/leapsecs_table.c | 54 +++++++++++++++++------------------ src/libstddjb/localtm_from_ltm64.c | 5 ++-- src/libstddjb/localtm_from_sysclock.c | 2 +- src/libstddjb/localtm_from_tai.c | 4 +-- src/libstddjb/localtm_from_utc.c | 2 +- src/libstddjb/utc_from_tai.c | 5 ++-- tools/convert-leapsecs.c | 2 +- 8 files changed, 42 insertions(+), 38 deletions(-) diff --git a/doc/libstddjb/djbtime.html b/doc/libstddjb/djbtime.html index f4d280d..724cd66 100644 --- a/doc/libstddjb/djbtime.html +++ b/doc/libstddjb/djbtime.html @@ -57,7 +57,8 @@ Converts the absolute TAI64 time in *t to an UTC time, stored in *u as an unsigned 64-bit integer. *u is actually 2^62 plus the number of seconds since the Epoch. The function returns 1 if it succeeds, or 0 (and sets errno) if an -error occurs. +error occurs. If *t happens to hit a leap second, the function +returns 2 instead of 1.

@@ -106,7 +107,8 @@ Converts the TAI time in *t to broken-down GMT (if *tm. The function returns 1 if it succeeds, or 0 (and sets errno) if an error occurs (for instance: *t cannot be validly represented -in a struct tm). +in a struct tm). If *t happens to hit a leap second, the +value of tm→tm_sec is 60.

diff --git a/src/libstddjb/leapsecs_table.c b/src/libstddjb/leapsecs_table.c index 5fd538b..32ffb19 100644 --- a/src/libstddjb/leapsecs_table.c +++ b/src/libstddjb/leapsecs_table.c @@ -9,32 +9,32 @@ unsigned int const leapsecs_table_len = 27 ; static uint64_t const leapsecs_table_[27] = { - TAI_MAGIC + 78796809, - TAI_MAGIC + 94694410, - TAI_MAGIC + 126230411, - TAI_MAGIC + 157766412, - TAI_MAGIC + 189302413, - TAI_MAGIC + 220924814, - TAI_MAGIC + 252460815, - TAI_MAGIC + 283996816, - TAI_MAGIC + 315532817, - TAI_MAGIC + 362793618, - TAI_MAGIC + 394329619, - TAI_MAGIC + 425865620, - TAI_MAGIC + 489024021, - TAI_MAGIC + 567993622, - TAI_MAGIC + 631152023, - TAI_MAGIC + 662688024, - TAI_MAGIC + 709948825, - TAI_MAGIC + 741484826, - TAI_MAGIC + 773020827, - TAI_MAGIC + 820454428, - TAI_MAGIC + 867715229, - TAI_MAGIC + 915148830, - TAI_MAGIC + 1136073631, - TAI_MAGIC + 1230768032, - TAI_MAGIC + 1341100833, - TAI_MAGIC + 1435708834, - TAI_MAGIC + 1483228835 + TAI_MAGIC + 78796800, + TAI_MAGIC + 94694401, + TAI_MAGIC + 126230402, + TAI_MAGIC + 157766403, + TAI_MAGIC + 189302404, + TAI_MAGIC + 220924805, + TAI_MAGIC + 252460806, + TAI_MAGIC + 283996807, + TAI_MAGIC + 315532808, + TAI_MAGIC + 362793609, + TAI_MAGIC + 394329610, + TAI_MAGIC + 425865611, + TAI_MAGIC + 489024012, + TAI_MAGIC + 567993613, + TAI_MAGIC + 631152014, + TAI_MAGIC + 662688015, + TAI_MAGIC + 709948816, + TAI_MAGIC + 741484817, + TAI_MAGIC + 773020818, + TAI_MAGIC + 820454419, + TAI_MAGIC + 867715220, + TAI_MAGIC + 915148821, + TAI_MAGIC + 1136073622, + TAI_MAGIC + 1230768023, + TAI_MAGIC + 1341100824, + TAI_MAGIC + 1435708825, + TAI_MAGIC + 1483228826 } ; uint64_t const *const leapsecs_table = leapsecs_table_ ; diff --git a/src/libstddjb/localtm_from_ltm64.c b/src/libstddjb/localtm_from_ltm64.c index 76703da..a115cdc 100644 --- a/src/libstddjb/localtm_from_ltm64.c +++ b/src/libstddjb/localtm_from_ltm64.c @@ -12,7 +12,7 @@ #include #include -int localtm_from_ltm64 (struct tm *l, uint64_t uu, int tz) +int localtm_from_ltm64 (struct tm *l, uint64_t uu, int tzh) { if (uu < TAI_MAGIC) return (errno = EINVAL, 0) ; uu -= TAI_MAGIC ; @@ -21,7 +21,8 @@ int localtm_from_ltm64 (struct tm *l, uint64_t uu, int tz) #endif { time_t u = (time_t)uu ; - if (tz ? !localtime_r(&u, l) : !gmtime_r(&u, l)) return 0 ; + if (tzh & 1 ? !localtime_r(&u, l) : !gmtime_r(&u, l)) return 0 ; } + if (tzh & 2) l->tm_sec++ ; return 1 ; } diff --git a/src/libstddjb/localtm_from_sysclock.c b/src/libstddjb/localtm_from_sysclock.c index d63a6d8..02a9f67 100644 --- a/src/libstddjb/localtm_from_sysclock.c +++ b/src/libstddjb/localtm_from_sysclock.c @@ -7,5 +7,5 @@ int localtm_from_sysclock (struct tm *l, uint64_t u, int tz) { if (!ltm64_from_sysclock(&u)) return 0 ; - return localtm_from_ltm64(l, u, tz) ; + return localtm_from_ltm64(l, u, !!tz) ; } diff --git a/src/libstddjb/localtm_from_tai.c b/src/libstddjb/localtm_from_tai.c index 23705ba..c11131c 100644 --- a/src/libstddjb/localtm_from_tai.c +++ b/src/libstddjb/localtm_from_tai.c @@ -7,6 +7,6 @@ int localtm_from_tai (struct tm *l, tai_t const *t, int tz) { uint64_t u ; - if (!ltm64_from_tai(&u, t)) return 0 ; - return localtm_from_ltm64(l, u, tz) ; + int h = ltm64_from_tai(&u, t) ; + return h ? localtm_from_ltm64(l, u, !!tz | (h & 2)) : 0 ; } diff --git a/src/libstddjb/localtm_from_utc.c b/src/libstddjb/localtm_from_utc.c index cbf6f31..55e9c5e 100644 --- a/src/libstddjb/localtm_from_utc.c +++ b/src/libstddjb/localtm_from_utc.c @@ -7,5 +7,5 @@ int localtm_from_utc (struct tm *l, uint64_t u, int tz) { if (!ltm64_from_utc(&u)) return 0 ; - return localtm_from_ltm64(l, u, tz) ; + return localtm_from_ltm64(l, u, !!tz) ; } diff --git a/src/libstddjb/utc_from_tai.c b/src/libstddjb/utc_from_tai.c index 0b46721..a0e087e 100644 --- a/src/libstddjb/utc_from_tai.c +++ b/src/libstddjb/utc_from_tai.c @@ -6,9 +6,10 @@ int utc_from_tai (uint64_t *u, tai_t const *t) { + int r = 1 ; uint64_t tt = t->x - 10 ; if (t->x < 10U) return (errno = EINVAL, 0) ; - leapsecs_sub(&tt) ; + r += leapsecs_sub(&tt) ; *u = tt ; - return 1 ; + return r ; } diff --git a/tools/convert-leapsecs.c b/tools/convert-leapsecs.c index 27f8507..78e0f73 100644 --- a/tools/convert-leapsecs.c +++ b/tools/convert-leapsecs.c @@ -41,7 +41,7 @@ int main (int argc, char const *const *argv) tm.tm_hour = 23 ; t = mktime(&tm) ; if (t < 0) strerr_diefu1sys(111, "mktime") ; - tt = t + 10 ; + tt = t + 1 ; add_leapsecs(&tt) ; if (!genalloc_append(uint64_t, &table, &tt)) strerr_diefu1sys(111, "genalloc_append") ; -- cgit v1.2.3