about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/index.html2
-rw-r--r--doc/libstddjb/djbtime.html23
-rw-r--r--doc/libstddjb/tai.html25
-rw-r--r--doc/upgrade.html6
-rw-r--r--package/deps.mak5
-rw-r--r--package/info2
-rw-r--r--src/etc/leapsecs.datbin208 -> 0 bytes
-rw-r--r--src/libstddjb/djbtime-internal.h21
-rw-r--r--src/libstddjb/leapsecs_add.c11
-rw-r--r--src/libstddjb/leapsecs_here.c9
-rw-r--r--src/libstddjb/leapsecs_init.c34
-rw-r--r--src/libstddjb/leapsecs_sub.c10
-rw-r--r--src/libstddjb/leapsecs_table.c39
-rw-r--r--src/libstddjb/ltm64_from_utc.c2
-rw-r--r--src/libstddjb/tai_from_utc.c2
-rw-r--r--src/libstddjb/utc_from_localtm.c6
-rw-r--r--src/libstddjb/utc_from_ltm64.c14
-rw-r--r--src/libstddjb/utc_from_tai.c2
-rw-r--r--tools/convert-leapsecs.c53
-rw-r--r--tools/leapsecs.txt29
-rwxr-xr-xtools/make-leapsecs_table39
21 files changed, 195 insertions, 139 deletions
diff --git a/doc/index.html b/doc/index.html
index f97bf25..12d718e 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -60,7 +60,7 @@ with a standard C development environment </li>
 <h3> Download </h3>
 
 <ul>
- <li> The current released version of skalibs is <a href="skalibs-2.3.7.1.tar.gz">2.3.7.1</a>. </li>
+ <li> The current released version of skalibs is <a href="skalibs-2.3.8.0.tar.gz">2.3.8.0</a>. </li>
  <li> Alternatively, you can checkout a copy of the skalibs git repository:
 <pre> git clone git://git.skarnet.org/skalibs </pre> </li>
 </ul>
diff --git a/doc/libstddjb/djbtime.html b/doc/libstddjb/djbtime.html
index 7eb5ee4..d20131e 100644
--- a/doc/libstddjb/djbtime.html
+++ b/doc/libstddjb/djbtime.html
@@ -34,21 +34,6 @@ and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library.
 other time formats and user-friendly representations.
 </p>
 
-<h2> The <tt>/etc/leapsecs.dat</tt> file </h2>
-
-<p>
- User-friendly time is calculated from UTC. Internal time computations
-should be performed on TAI time - because TAI flows linearly whereas
-UTC does not. To convert between UTC and TAI time, you need a
-<em>leap second table</em>. skalibs provides such a file in its
-<tt>src/etc/leapsecs.dat</tt> subdirectory, which is copied
-to <tt>/etc/leapsecs.dat</tt> at installation time (unless you specify
-a --prefix or --datadir option to configure).
-<strong>The <tt>/etc/leapsecs.dat</tt> file must remain accessible
-on your system, else time conversions will not be computed
-properly.</strong>
-</p>
-
 <h2> Data structures </h2>
 
 <ul>
@@ -72,7 +57,7 @@ Converts the absolute TAI64 time in *<em>t</em> to an UTC time, stored in
 *<em>u</em> as an unsigned 64-bit integer. *<em>u</em> 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 (for instance: the leap second table cannot be found).
+error occurs.
 </p>
 
 <p>
@@ -81,7 +66,7 @@ Converts the UTC time in <em>u</em>, stored
 as an unsigned 64-bit integer (2^62 plus the number of seconds since
 the Epoch), to a TAI64 time in *<em>t</em>.
 The function returns 1 if it succeeds, or 0 (and sets errno) if an
-error occurs (for instance: the leap second table cannot be found).
+error occurs.
 </p>
 
 <h3> NTP </h3>
@@ -92,7 +77,7 @@ Converts the absolute TAI64N time in *<em>a</em> to a 64-bit NTP timestamp,
 stored in *<em>ntp</em>. The higher 32 bits of *<em>ntp</em> represent a number
 of seconds ; the lower 32 bits are the fractional part of the timestamp.
 The function returns 1 if it succeeds, or 0 (and sets errno) if an
-error occurs (for instance: the leap second table cannot be found, or
+error occurs (for instance:
 *<em>a</em> cannot be represented in the valid NTP range).
 </p>
 
@@ -101,7 +86,7 @@ error occurs (for instance: the leap second table cannot be found, or
 Converts the NTP timestamp in <em>ntp</em> to a TAI64N time in
 *<em>a</em>.
 The function returns 1 if it succeeds, or 0 (and sets errno) if an
-error occurs (for instance: the leap second table cannot be found).
+error occurs.
 </p>
 
 <h3> Local time </h3>
diff --git a/doc/libstddjb/tai.html b/doc/libstddjb/tai.html
index a285cfb..231c0d1 100644
--- a/doc/libstddjb/tai.html
+++ b/doc/libstddjb/tai.html
@@ -112,28 +112,6 @@ dates. It is up to the programmer to make sure that a relative time is
 never interpreted as an absolute TAI64 date, and vice-versa.
 </p>
 
-<h3> The leap second table </h3>
-
-<p>
- skalibs provides a <tt>src/etc/leapsecs.dat</tt> file,
-which is copied to <tt>/etc/leapsecs.dat</tt> at installation time
-(or wherever you specified with the <tt>--prefix</tt> or <tt>--datadir</tt>
-options to configure).
-<strong>Make sure this file is always present and readable.</strong>
-This file contains the <em>leap second table</em>, which is needed for
-conversions between TAI and UTC. If you call a function that needs such
-a conversion (for instance, you call <tt>tain_sysclock()</tt> and your
-system clock is set to UTC) and the file cannot be read, the function
-call will fail.
-</p>
-
-<p>
- The leap second table is read once in every process that needs it
-(the first time a TAI &harr; UTC conversion is made) and then is
-stored in memory. If the <tt>leapsecs.dat</tt> file changes, long-lived
-processes will need to be restarted to take the change into account.
-</p>
-
 <h2> Functions </h2>
 
 <h3> Wallclock operations </h3>
@@ -343,8 +321,7 @@ could not be performed; in which case errno is set to EINVAL if
 the input argument was not a valid timestamp, to EOVERFLOW if the
 output could not be represented in the chosen format (which may
 happen on systems with a 32 bit <tt>time_t</tt>), or other error
-codes - for instance related to the leap second table when a
-lookup was necessary.
+codes.
 </p>
 
 <code> int tai_from_time_sysclock (tai_t *a, time_t t) <br />
diff --git a/doc/upgrade.html b/doc/upgrade.html
index d445290..1e9d318 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,12 @@
 
 <h1> What has changed in skalibs </h1>
 
+<h2> in 2.3.8.0 </h2>
+
+<ul>
+ <li> The <tt>/etc/leapsecs.dat</tt> file is no longer necessary. </li>
+</ul>
+
 <h2> in 2.3.7.1 </h2>
 
 <ul>
diff --git a/package/deps.mak b/package/deps.mak
index 93923b6..7a4b6d9 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -68,7 +68,7 @@ src/libstdcrypto/sha1-internal.h: src/include/skalibs/sha1.h src/include/skalibs
 src/libstdcrypto/sha256-internal.h: src/include/skalibs/sha256.h src/include/skalibs/uint32.h
 src/libstdcrypto/sha512-internal.h: src/include/skalibs/sha512.h
 src/libstddjb/alloc-internal.h: src/include/skalibs/alloc.h src/include/skalibs/sysdeps.h
-src/libstddjb/djbtime-internal.h: src/include/skalibs/config.h src/include/skalibs/uint64.h
+src/libstddjb/djbtime-internal.h: src/include/skalibs/uint64.h
 src/libstddjb/fmtscan-internal.h: src/include/skalibs/bytestr.h src/include/skalibs/fmtscan.h
 src/libstddjb/selfpipe-internal.h: src/include/skalibs/sig.h src/include/skalibs/sysdeps.h
 src/libunixonacid/skaclient-internal.h: src/include/skalibs/kolbak.h src/include/skalibs/skaclient.h src/include/skalibs/unixmessage.h
@@ -405,9 +405,8 @@ src/libstddjb/ipc_send.o src/libstddjb/ipc_send.lo: src/libstddjb/ipc_send.c src
 src/libstddjb/ipc_stream.o src/libstddjb/ipc_stream.lo: src/libstddjb/ipc_stream.c src/include/skalibs/djbunix.h src/include/skalibs/nonposix.h src/include/skalibs/webipc.h
 src/libstddjb/ipc_timed_connect.o src/libstddjb/ipc_timed_connect.lo: src/libstddjb/ipc_timed_connect.c src/include/skalibs/error.h src/include/skalibs/iopause.h src/include/skalibs/tai.h src/include/skalibs/webipc.h
 src/libstddjb/leapsecs_add.o src/libstddjb/leapsecs_add.lo: src/libstddjb/leapsecs_add.c src/libstddjb/djbtime-internal.h src/include/skalibs/uint64.h
-src/libstddjb/leapsecs_here.o src/libstddjb/leapsecs_here.lo: src/libstddjb/leapsecs_here.c src/libstddjb/djbtime-internal.h src/include/skalibs/uint64.h
-src/libstddjb/leapsecs_init.o src/libstddjb/leapsecs_init.lo: src/libstddjb/leapsecs_init.c src/libstddjb/djbtime-internal.h src/include/skalibs/djbunix.h src/include/skalibs/uint64.h
 src/libstddjb/leapsecs_sub.o src/libstddjb/leapsecs_sub.lo: src/libstddjb/leapsecs_sub.c src/libstddjb/djbtime-internal.h src/include/skalibs/uint64.h
+src/libstddjb/leapsecs_table.o src/libstddjb/leapsecs_table.lo: src/libstddjb/leapsecs_table.c src/libstddjb/djbtime-internal.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/localtm_fmt.o src/libstddjb/localtm_fmt.lo: src/libstddjb/localtm_fmt.c src/include/skalibs/djbtime.h src/include/skalibs/uint.h
 src/libstddjb/localtm_from_ltm64.o src/libstddjb/localtm_from_ltm64.lo: src/libstddjb/localtm_from_ltm64.c src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/localtm_from_sysclock.o src/libstddjb/localtm_from_sysclock.lo: src/libstddjb/localtm_from_sysclock.c src/include/skalibs/djbtime.h src/include/skalibs/uint64.h
diff --git a/package/info b/package/info
index d7ed139..e19f829 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=skalibs
-version=2.3.7.1
+version=2.3.8.0
 category=prog
 package_macro_name=SKALIBS
diff --git a/src/etc/leapsecs.dat b/src/etc/leapsecs.dat
deleted file mode 100644
index dde501d..0000000
--- a/src/etc/leapsecs.dat
+++ /dev/null
Binary files differdiff --git a/src/libstddjb/djbtime-internal.h b/src/libstddjb/djbtime-internal.h
index f402832..eb4e676 100644
--- a/src/libstddjb/djbtime-internal.h
+++ b/src/libstddjb/djbtime-internal.h
@@ -3,26 +3,13 @@
 #ifndef DJBTIME_INTERNAL_H
 #define DJBTIME_INTERNAL_H
 
-#include <skalibs/config.h>
 #include <skalibs/uint64.h>
 
+extern unsigned int const leapsecs_table_len ;
+extern uint64 const *const leapsecs_table ;
 
- /* Leap second handling, for UTC <--> TAI conversions */
-
-#define LEAPSECS_MAX 39
-#define LEAPSECS_FILE SKALIBS_ETC "/leapsecs.dat"
-extern uint64 *leapsecs_here ;
-
-extern int leapsecs_init_r (char const *, uint64 *) ;
-#define leapsecs_init() leapsecs_init_r(LEAPSECS_FILE, leapsecs_here)
-extern int leapsecs_add_r (uint64 *, char const *, uint64 *, int) ;
-#define leapsecs_add(t, h) leapsecs_add_r(t, LEAPSECS_FILE, leapsecs_here, h)
-extern int leapsecs_sub_r (uint64 *, char const *, uint64 *) ;
-#define leapsecs_sub(t) leapsecs_sub_r((t), LEAPSECS_FILE, leapsecs_here)
-
-
- /* Run-time test: does the current timezone handle leap seconds ? */
-
+extern void leapsecs_add (uint64 *, int) ;
+extern int leapsecs_sub (uint64 *) ;
 extern int skalibs_tzisright (void) ;
 
 #endif
diff --git a/src/libstddjb/leapsecs_add.c b/src/libstddjb/leapsecs_add.c
index c24486b..4b75f7d 100644
--- a/src/libstddjb/leapsecs_add.c
+++ b/src/libstddjb/leapsecs_add.c
@@ -3,17 +3,14 @@
 #include <skalibs/uint64.h>
 #include "djbtime-internal.h"
 
-int leapsecs_add_r (uint64 *t, char const *file, uint64 *leapsecs, int hit)
+void leapsecs_add (uint64 *t, int hit)
 {
   uint64 u = *t ;
-  int n = leapsecs_init_r(file, leapsecs) ;
   register unsigned int i = 0 ;
-  if (n < 0) return -1 ;
-  for (; i < (unsigned int)n ; i++)
+  for (; i < leapsecs_table_len ; i++)
   {
-    if (u < leapsecs[i]) break ;
-    if (!hit || (leapsecs[i] < u)) ++u ;
+    if (u < leapsecs_table[i]) break ;
+    if (!hit || (leapsecs_table[i] < u)) ++u ;
   }
   *t = u ;
-  return n ;
 }
diff --git a/src/libstddjb/leapsecs_here.c b/src/libstddjb/leapsecs_here.c
deleted file mode 100644
index 3ecdfd1..0000000
--- a/src/libstddjb/leapsecs_here.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* ISC license. */
-
-/* MT-unsafe */
-
-#include <skalibs/uint64.h>
-#include "djbtime-internal.h"
-
-static uint64 leapsecs_here_tab[LEAPSECS_MAX+1] ;
-uint64 *leapsecs_here = leapsecs_here_tab ;
diff --git a/src/libstddjb/leapsecs_init.c b/src/libstddjb/leapsecs_init.c
deleted file mode 100644
index 41f9b89..0000000
--- a/src/libstddjb/leapsecs_init.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* ISC license. */
-
-#include <errno.h>
-#include <skalibs/uint64.h>
-#include <skalibs/djbunix.h>
-#include "djbtime-internal.h"
-
-static unsigned int leapsecs_len (uint64 const *data)
-{
-  register unsigned int i = 1 ;
-  while (data[i]) i++ ;
-  return i ;
-}
-
-static int leapsecs_read (char const *file, uint64 *data)
-{
-  char s[LEAPSECS_MAX * sizeof(uint64)] ;
-  register int n = openreadnclose(file, s, LEAPSECS_MAX * sizeof(uint64)) ;
-  if (n < 0) return -1 ;
-  if (n % sizeof(uint64)) return (errno = EINVAL, -1) ;
-  n /= sizeof(uint64) ;
-  {
-    register unsigned int i = 0 ;
-    for (; i < (unsigned int)n ; i++)
-      uint64_unpack_big(s + i * sizeof(uint64), data + i) ;
-  }
-  data[n] = 0 ;
-  return n ;
-}
-
-int leapsecs_init_r (char const *file, uint64 *data)
-{
-  return data[0] ? (int)leapsecs_len(data) : leapsecs_read(file, data) ;
-}
diff --git a/src/libstddjb/leapsecs_sub.c b/src/libstddjb/leapsecs_sub.c
index 271f592..f466fac 100644
--- a/src/libstddjb/leapsecs_sub.c
+++ b/src/libstddjb/leapsecs_sub.c
@@ -3,19 +3,17 @@
 #include <skalibs/uint64.h>
 #include "djbtime-internal.h"
 
-int leapsecs_sub_r (uint64 *t, char const *file, uint64 *leapsecs)
+int leapsecs_sub (uint64 *t)
 {
   uint64 u = *t ;
   uint64 d = 0 ;
-  int n = leapsecs_init_r(file, leapsecs) ;
   register unsigned int i = 0 ;
   register int hit = 0 ;
-  if (n < 0) return -1 ;
-  for (; i < (unsigned int)n ; i++)
+  for (; i < leapsecs_table_len ; i++)
   {
-    if (u < leapsecs[i]) break ;
+    if (u < leapsecs_table[i]) break ;
     ++d ;
-    if (u == leapsecs[i]) hit = 1 ;
+    if (u == leapsecs_table[i]) hit = 1 ;
   }
   *t = u - d ;
   return hit ;
diff --git a/src/libstddjb/leapsecs_table.c b/src/libstddjb/leapsecs_table.c
new file mode 100644
index 0000000..d5a32a9
--- /dev/null
+++ b/src/libstddjb/leapsecs_table.c
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/uint64.h>
+#include <skalibs/tai.h>
+#include "djbtime-internal.h"
+
+unsigned int const leapsecs_table_len = 26 ;
+static uint64 const leapsecs_table_[26] =
+{
+  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
+} ;
+uint64 const *const leapsecs_table = leapsecs_table_ ;
diff --git a/src/libstddjb/ltm64_from_utc.c b/src/libstddjb/ltm64_from_utc.c
index 28907c9..7e08eb1 100644
--- a/src/libstddjb/ltm64_from_utc.c
+++ b/src/libstddjb/ltm64_from_utc.c
@@ -8,7 +8,7 @@ int ltm64_from_utc (uint64 *u)
 {
   switch (skalibs_tzisright())
   {
-    case 1 : return leapsecs_add(u, 0) >= 0 ;
+    case 1 : leapsecs_add(u, 0) ;
     case 0 : return 1 ;
     default : return 0 ;
   }
diff --git a/src/libstddjb/tai_from_utc.c b/src/libstddjb/tai_from_utc.c
index c5dc62d..3f4d5ec 100644
--- a/src/libstddjb/tai_from_utc.c
+++ b/src/libstddjb/tai_from_utc.c
@@ -7,6 +7,6 @@
 
 int tai_from_utc (tai_t *t, uint64 u)
 {
-  if (leapsecs_add(&u, 0) < 0) return 0 ;
+  leapsecs_add(&u, 0) ;
   return tai_u64(t, u + 10) ;
 }
diff --git a/src/libstddjb/utc_from_localtm.c b/src/libstddjb/utc_from_localtm.c
index cad1a06..a5886f3 100644
--- a/src/libstddjb/utc_from_localtm.c
+++ b/src/libstddjb/utc_from_localtm.c
@@ -7,9 +7,7 @@
 
 int utc_from_localtm (uint64 *uu, struct tm const *l)
 {
-  uint64 u ;
-  if (!ltm64_from_localtm(&u, l)) return 0 ;
-  if (!utc_from_ltm64(&u)) return 0 ;
-  *uu = u ;
+  if (!ltm64_from_localtm(uu, l)) return 0 ;
+  utc_from_ltm64(uu) ;
   return 1 ;
 }
diff --git a/src/libstddjb/utc_from_ltm64.c b/src/libstddjb/utc_from_ltm64.c
index 44aea15..788a539 100644
--- a/src/libstddjb/utc_from_ltm64.c
+++ b/src/libstddjb/utc_from_ltm64.c
@@ -5,19 +5,11 @@
 #include <skalibs/djbtime.h>
 #include "djbtime-internal.h"
 
-#ifdef SKALIBS_FLAG_CLOCKISTAI
-
-int utc_from_ltm64 (uint64 *u)
-{
-  return (leapsecs_sub(u) > 0) ;
-}
-
-#else
 
 int utc_from_ltm64 (uint64 *u)
 {
-  (void)u ;
+#ifdef SKALIBS_FLAG_CLOCKISTAI
+  leapsecs_sub(u) ;
+#endif
   return 1 ;
 }
-
-#endif
diff --git a/src/libstddjb/utc_from_tai.c b/src/libstddjb/utc_from_tai.c
index 80d2763..1e5e094 100644
--- a/src/libstddjb/utc_from_tai.c
+++ b/src/libstddjb/utc_from_tai.c
@@ -10,7 +10,7 @@ int utc_from_tai (uint64 *u, tai_t const *t)
 {
   uint64 tt = t->x - 10 ;
   if (t->x < 10U) return (errno = EINVAL, 0) ;
-  if (leapsecs_sub(&tt) < 0) return 0 ;
+  leapsecs_sub(&tt) ;
   *u = tt ;
   return 1 ;
 }
diff --git a/tools/convert-leapsecs.c b/tools/convert-leapsecs.c
new file mode 100644
index 0000000..82410e6
--- /dev/null
+++ b/tools/convert-leapsecs.c
@@ -0,0 +1,53 @@
+#include <time.h>
+#include <skalibs/uint64.h>
+#include <skalibs/buffer.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/skamisc.h>
+
+static genalloc table = GENALLOC_ZERO ; /* uint64 */
+
+static void add_leapsecs (uint64 *t)
+{
+  uint64 *tab = genalloc_s(uint64, &table) ;
+  unsigned int n = genalloc_len(uint64, &table) ;
+  unsigned int i = 0 ;
+  for (; i < n ; i++) if (*t >= tab[i]) (*t)++ ;
+}
+
+int main (int argc, char const *const *argv)
+{
+  stralloc sa = STRALLOC_ZERO ;
+  for (;;)
+  {
+    struct tm tm ;
+    uint64 tt ;
+    time_t t ;
+    char *p ;
+    int r ;
+    char fmt[UINT64_FMT] ;
+    sa.len = 0 ;
+    r = skagetln(buffer_0, &sa, '\n') ;
+    if (r < 0) strerr_diefu1sys(111, "read from stdin") ;
+    if (!r) break ;
+    sa.s[sa.len-1] = 0 ;
+    if (!strptime(sa.s, "+%Y-%m-%d", &tm)) continue ;
+    tm.tm_sec = 59 ;
+    tm.tm_min = 59 ;
+    tm.tm_hour = 23 ;
+    t = mktime(&tm) ;
+    if (t < 0) strerr_diefu1sys(111, "mktime") ;
+    tt = t + 10 ;
+    add_leapsecs(&tt) ;
+    if (!genalloc_append(uint64, &table, &tt))
+      strerr_diefu1sys(111, "genalloc_append") ;
+    fmt[uint64_fmt(fmt, tt)] = 0 ;
+    buffer_puts(buffer_1, "  TAI_MAGIC + ") ;
+    buffer_puts(buffer_1, fmt) ;
+    buffer_puts(buffer_1, ",\n") ;
+  }
+  buffer_unput(buffer_1, 2) ;
+  buffer_putsflush(buffer_1, "\n") ;
+  return 0 ;
+}
diff --git a/tools/leapsecs.txt b/tools/leapsecs.txt
new file mode 100644
index 0000000..fa2a965
--- /dev/null
+++ b/tools/leapsecs.txt
@@ -0,0 +1,29 @@
+#
+# 1972-01-01 00:00:00 UTC was 1972-01-01 00:00:10 TAI.
+# 
++1972-06-30
++1972-12-31
++1973-12-31
++1974-12-31
++1975-12-31
++1976-12-31
++1977-12-31
++1978-12-31
++1979-12-31
++1981-06-30
++1982-06-30
++1983-06-30
++1985-06-30
++1987-12-31
++1989-12-31
++1990-12-31
++1992-06-30
++1993-06-30
++1994-06-30
++1995-12-31
++1997-06-30
++1998-12-31
++2005-12-31
++2008-12-31
++2012-06-30
++2015-06-30
diff --git a/tools/make-leapsecs_table b/tools/make-leapsecs_table
new file mode 100755
index 0000000..c62fdde
--- /dev/null
+++ b/tools/make-leapsecs_table
@@ -0,0 +1,39 @@
+#!/command/execlineb -P
+
+# Compile convert-leapsecs.c, then use this to create
+# src/libstddjb/leapsecs_table.c
+
+define PREFIX ./tools
+
+backtick -n N
+{
+  pipeline
+  {
+    redirfd -r 0 ${PREFIX}/leapsecs.txt
+    ${PREFIX}/convert-leapsecs
+  }
+  wc -l
+}
+import -u N
+
+if
+{
+  s6-echo "/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/uint64.h>
+#include <skalibs/tai.h>
+#include \"djbtime-internal.h\"
+
+unsigned int const leapsecs_table_len = ${N} ;
+static uint64 const leapsecs_table_[${N}] =\n{"
+}
+
+if
+{
+  redirfd -r 0 ${PREFIX}/leapsecs.txt
+  ${PREFIX}/convert-leapsecs
+}
+
+s6-echo "} ;\nuint64 const *const leapsecs_table = leapsecs_table_ ;"