summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/index.html2
-rw-r--r--doc/libstddjb/tai.html107
-rw-r--r--doc/upgrade.html7
-rw-r--r--package/deps.mak20
-rw-r--r--package/info2
-rw-r--r--src/include/skalibs/tai.h38
-rw-r--r--src/libstddjb/sysclock_from_localtmn.c4
-rw-r--r--src/libstddjb/sysclock_from_tai.c2
-rw-r--r--src/libstddjb/sysclock_from_tain.c10
-rw-r--r--src/libstddjb/sysclock_from_utc.c2
-rw-r--r--src/libstddjb/tai_add.c4
-rw-r--r--src/libstddjb/tai_from_ltm64.c2
-rw-r--r--src/libstddjb/tai_from_sysclock.c3
-rw-r--r--src/libstddjb/tai_from_timespec.c11
-rw-r--r--src/libstddjb/tai_from_timeval.c10
-rw-r--r--src/libstddjb/tai_from_utc.c4
-rw-r--r--src/libstddjb/tai_now.c6
-rw-r--r--src/libstddjb/tai_relative_from_timespec.c11
-rw-r--r--src/libstddjb/tai_relative_from_timeval.c10
-rw-r--r--src/libstddjb/tai_sub.c4
-rw-r--r--src/libstddjb/tai_u64.c12
-rw-r--r--src/libstddjb/tain_add.c15
-rw-r--r--src/libstddjb/tain_addsec.c13
-rw-r--r--src/libstddjb/tain_from_ntp.c2
-rw-r--r--src/libstddjb/tain_from_sysclock.c10
-rw-r--r--src/libstddjb/tain_from_timespec.c8
-rw-r--r--src/libstddjb/tain_from_timespec_sysclock.c11
-rw-r--r--src/libstddjb/tain_from_timeval.c7
-rw-r--r--src/libstddjb/tain_from_timeval_sysclock.c11
-rw-r--r--src/libstddjb/tain_half.c6
-rw-r--r--src/libstddjb/tain_relative_from_timespec.c4
-rw-r--r--src/libstddjb/tain_relative_from_timeval.c3
-rw-r--r--src/libstddjb/tain_sub.c16
-rw-r--r--src/libstddjb/tain_sysclock.c4
-rw-r--r--src/libstddjb/tain_ulong.c5
-rw-r--r--src/libstddjb/time_from_tai.c17
-rw-r--r--src/libstddjb/time_from_tai_relative.c16
-rw-r--r--src/libstddjb/time_sysclock_from_tai.c20
-rw-r--r--src/libstddjb/timespec_from_tai.c12
-rw-r--r--src/libstddjb/timespec_from_tai_relative.c19
-rw-r--r--src/libstddjb/timespec_from_tain.c9
-rw-r--r--src/libstddjb/timespec_from_tain_relative.c9
-rw-r--r--src/libstddjb/timespec_sysclock_from_tain.c11
-rw-r--r--src/libstddjb/timeval_from_tai.c11
-rw-r--r--src/libstddjb/timeval_from_tai_relative.c18
-rw-r--r--src/libstddjb/timeval_from_tain.c8
-rw-r--r--src/libstddjb/timeval_from_tain_relative.c8
-rw-r--r--src/libstddjb/timeval_sysclock_from_tain.c11
-rw-r--r--src/libstddjb/utc_from_tai.c2
49 files changed, 319 insertions, 238 deletions
diff --git a/doc/index.html b/doc/index.html
index d321235..1d206c1 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -59,7 +59,7 @@ with a standard C development environment </li>
 <h3> Download </h3>
 
 <ul>
- <li> The current released version of skalibs is <a href="skalibs-2.1.0.0.tar.gz">2.1.0.0</a>. </li>
+ <li> The current released version of skalibs is <a href="skalibs-2.2.0.0.tar.gz">2.2.0.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/tai.html b/doc/libstddjb/tai.html
index 3617959..0b1be3c 100644
--- a/doc/libstddjb/tai.html
+++ b/doc/libstddjb/tai.html
@@ -178,7 +178,7 @@ has been configured with (resp. without) the
 <a href="../flags.html#usert">--enable-clock</a>
 option. Returns 1 if it succeeds or 0 (and sets errno) if it
 fails.
- Here <em>a</em> contains a valid TAI stamp, no matter what the
+ Here <em>a</em> contains a valid TAI64N stamp, no matter what the
 system clock is set to: arithmetic operations can be performed
 on it.
 </p>
@@ -190,7 +190,7 @@ Sets the current time to *<em>a</em>, with a 1-nanosecond
 with (resp. without) the
 <a href="../flags.html#usert">--enable-clock</a>
 option. Returns 1 if it succeeds or 0 (and sets errno) if it
-fails. <em>a</em> must contain a valid TAI stamp; proper
+fails. <em>a</em> must contain a valid TAI64N stamp; proper
 operations will be automatically run to convert that stamp into
 the right format for the system clock.
 </p>
@@ -273,43 +273,92 @@ computations.
 <h3> Converting to/from libc representations </h3>
 
 <p>
-<code> int tai_from_timeval (tai_t *t, struct timeval const *tv) <br />
-int tai_from_timespec (tai_t *t, struct timespec const *ts) <br />
-int tai_relative_from_timeval (tai_t *t, struct timeval const *tv) <br />
-int tai_relative_from_timespec (tai_t *t, struct timespec const *ts) </code> <br />
+ The following functions only convert from a certain structure
+format to another; they do not make any assumption about the
+format of the time contained in those structures. For instance,
+for the <tt>tai_from_timeval</tt> function, if the struct timeval
+contains an absolute UTC time, then the tai_t will also contain
+the same UTC time. Despite being a tai_t, it may contain
+something else than TAI time.
+</p>
+
+<p>
+If you need conversion from the native machine
+system clock format to TAI, see the next section.
+</p>
+
+<p>
+<code> int tai_from_time (tai_t *t, time_t u) <br />
+int tai_relative_from_time (tai_t *t, time_t u) </code> <br />
 Those functions convert an absolute (resp. relative) time in a
-struct timeval (resp. struct timespec) to an absolute (resp. relative)
-time in a tai_t, with a 1-second precision. They return 1.
+time_t to an absolute (resp. relative)
+time in a tai_t, with a 1-second precision. They return 1,
+unless the time_t value is invalid (in which case they return 0).
 </p>
 
 <p>
-<code> int timeval_from_tai (struct timeval *tv, tai_t const *t) <br />
-int timespec_from_tai (struct timespec *ts, tai_t const *t) <br />
-int timeval_from_tai_relative (struct timeval *tv, tai_t const *t) <br />
-int timespec_from_tai_relative (struct timespec *ts, tai_t const *t) </code> <br />
-Those functions do the opposite conversion. They normally return 1;
-however, <tt>struct timeval</tt> and <tt>struct timespec</tt> cannot
-represent an absolute date before the Epoch, or a negative relative time;
-if *<em>t</em> cannot be converted, 0 EINVAL is returned.
+<code> int time_from_tai (time_t *u, tai_t const *t) <br />
+int time_from_tai_relative (time_t *u, tai_t const *t) </code> <br />
+The inverse functions of the previous ones. Be aware that
+time_t is 32 bits on some systems and cannot store all values
+of a tai_t (in which case the functions will return 0 EOVERFLOW).
 </p>
 
 <p>
 <code> int tain_from_timeval (tain_t *a, struct timeval const *tv) <br />
-int tain_from_timespec (tain_t *a, struct timespec const *ts) <br />
 int tain_relative_from_timeval (tain_t *a, struct timeval const *tv) <br />
+int tain_from_timespec (tain_t *a, struct timespec const *ts) <br />
 int tain_relative_from_timespec (tain_t *a, struct timespec const *ts) <br />
 int timeval_from_tain (struct timeval *tv, tain_t const *a) <br />
-int timespec_from_tain (struct timespec *ts, tain_t const *a) <br />
 int timeval_from_tain_relative (struct timeval *tv, tain_t const *a) <br />
+int timespec_from_tain (struct timespec *ts, tain_t const *a) <br />
 int timespec_from_tain_relative (struct timespec *ts, tain_t const *a) </code> <br />
-Same conversion operations, but with a <tt>tain_t</tt>. The 1-microsecond
+Same conversion operations, between <tt>tain_t</tt> and a
+<tt>struct timeval</tt> or <tt>struct timespec</tt>. The 1-microsecond
 (for <tt>struct timeval</tt>) or 1-nanosecond (for <tt>struct timespec</tt>)
 precision is preserved.
 </p>
 
+<h3> Conversion between TAI and the system clock format </h3>
+
+<p>
+ Unlike the previous functions, the functions listed here will
+always operate on valid absolute timestamps. Only TAI64 time is
+stored in tai_t structures, and only TAI64N time is stored in
+tain_t structures. These functions will convert to/from TAI,
+from/to the machine system clock format, i.e. TAI-10 or UTC
+depending on whether skalibs was
+compiled with the --enable-tai-clock configure option).
+This is useful to get valid TAI/TAI64N timestamps out of
+information exported by the system, for instance the time_t
+returned by <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html">time()</a>,
+or in the <tt>st_atim</tt>, <tt>st_mtim</tt> or
+<tt>st_ctim</tt> fields of a <tt>struct stat</tt>.
+</p>
+
+<p>
+ The functions return 1 in case of success, or 0 if the conversion
+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.
+</p>
+
+<code> int tai_from_time_sysclock (tai_t *a, time_t t) <br />
+int time_sysclock_from_tai (time_t *t, tai_t const *a) <br />
+int tain_from_timeval_sysclock (tain_t *a, struct timeval const *tv) <br />
+int timeval_sysclock_from_tain (struct timeval *tv, tain_t const *a) <br /
+int tain_from_timespec_sysclock (tain_t *a, struct timespec const *ts) <br />
+int timespec_sysclock_from_tain (struct timespec *ts, tain_t const *a) </code>
+
+<h3> Conversions to/from basic types </h3>
+
 <p>
-<code> void tain_uint (tain_t *a, unsigned int c) </code> <br />
+<code> int tain_uint (tain_t *a, unsigned int c) </code> <br />
 Stores a relative time of <em>c</em> seconds into <em>a</em>.
+Normally returns 1, but may return 0 EINVAL on pathological numbers.
 </p>
 
 <p>
@@ -330,26 +379,28 @@ number. Else it returns -1 EINVAL.
 <h3> Time computations </h3>
 
 <p>
-<code> void tai_add (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br />
+<code> int tai_add (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br />
 Stores *<em>t1</em> + *<em>t2</em> into <em>t</em>. Of course, *<em>t1</em>
 and *<em>t2</em> must not both represent absolute times.
+The function normally returns 1, but will return 0 on bad inputs.
 </p>
 
 <p>
-<code> void tai_sub (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br />
-Stores *<em>t1</em> - *<em>t2</em> into <em>t</em>. Of course, *<em>t1</em>
-and *<em>t2</em> must be of the same type (relative or absolute), and
-*<em>t</em> will always be relative.
+<code> int tai_sub (tai_t *t, tai_t const *t1, tai_t const *t2) </code> <br />
+Stores *<em>t1</em> - *<em>t2</em> into <em>t</em>. *<em>t1</em> cannot
+be relative if *<em>t2</em> is absolute. If they are both relative or
+both absolute, then *<em>t</em> is relative, else it's absolute.
+The function normally returns 1, but will return 0 on bad inputs.
 </p>
 
 <p>
-<code> void tain_add (tain_t *a, tain_t const *a1, tain_t const *a2) <br />
-void tain_sub (tain_t *a, tain_t const *a1, tain_t const *a2) </code> <br />
+<code> int tain_add (tain_t *a, tain_t const *a1, tain_t const *a2) <br />
+int tain_sub (tain_t *a, tain_t const *a1, tain_t const *a2) </code> <br />
 Same thing with <tt>tain_t</tt>.
 </p>
 
 <p>
-<code> void tain_addsec (tain_t *a, tain_t const *a1, int c) </code> <br />
+<code> int tain_addsec (tain_t *a, tain_t const *a1, int c) </code> <br />
 Adds <em>c</em> seconds to *<em>a1</em> and stores the result into <em>a</em>.
 <em>c</em> may be negative.
 </p>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 8eb2a9a..bc9c0f4 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -17,6 +17,13 @@
 
 <h1> What has changed in skalibs </h1>
 
+<h2> in 2.2.0.0 </h2>
+
+<ul>
+ <li> TAI64 and TAI64N conversion functions revisited.
+API slightly changed, made more consistent. </li>
+</ul>
+
 <h2> in 2.1.0.0 </h2>
 
 <ul>
diff --git a/package/deps.mak b/package/deps.mak
index 3ab69cd..b38f35d 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -571,6 +571,7 @@ src/libstddjb/sysclock_from_localtm.o src/libstddjb/sysclock_from_localtm.lo: sr
 src/libstddjb/sysclock_from_localtmn.o src/libstddjb/sysclock_from_localtmn.lo: src/libstddjb/sysclock_from_localtmn.c src/include/skalibs/djbtime.h src/include/skalibs/tai.h
 src/libstddjb/sysclock_from_ltm64.o src/libstddjb/sysclock_from_ltm64.lo: src/libstddjb/sysclock_from_ltm64.c src/include/skalibs/config.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/sysclock_from_tai.o src/libstddjb/sysclock_from_tai.lo: src/libstddjb/sysclock_from_tai.c src/include/skalibs/config.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h
+src/libstddjb/sysclock_from_tain.o src/libstddjb/sysclock_from_tain.lo: src/libstddjb/sysclock_from_tain.c src/include/skalibs/tai.h
 src/libstddjb/sysclock_from_utc.o src/libstddjb/sysclock_from_utc.lo: src/libstddjb/sysclock_from_utc.c src/include/skalibs/config.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/sysclock_get.o src/libstddjb/sysclock_get.lo: src/libstddjb/sysclock_get.c src/include/skalibs/config.h src/include/skalibs/sysdeps.h src/include/skalibs/tai.h
 src/libstddjb/sysclock_set.o src/libstddjb/sysclock_set.lo: src/libstddjb/sysclock_set.c src/include/skalibs/config.h src/include/skalibs/nonposix.h src/include/skalibs/sysdeps.h src/include/skalibs/tai.h
@@ -578,15 +579,12 @@ src/libstddjb/tai_add.o src/libstddjb/tai_add.lo: src/libstddjb/tai_add.c src/in
 src/libstddjb/tai_from_localtm.o src/libstddjb/tai_from_localtm.lo: src/libstddjb/tai_from_localtm.c src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tai_from_ltm64.o src/libstddjb/tai_from_ltm64.lo: src/libstddjb/tai_from_ltm64.c src/libstddjb/djbtime-internal.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tai_from_sysclock.o src/libstddjb/tai_from_sysclock.lo: src/libstddjb/tai_from_sysclock.c src/include/skalibs/config.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h
-src/libstddjb/tai_from_timespec.o src/libstddjb/tai_from_timespec.lo: src/libstddjb/tai_from_timespec.c src/include/skalibs/tai.h
-src/libstddjb/tai_from_timeval.o src/libstddjb/tai_from_timeval.lo: src/libstddjb/tai_from_timeval.c src/include/skalibs/tai.h
 src/libstddjb/tai_from_utc.o src/libstddjb/tai_from_utc.lo: src/libstddjb/tai_from_utc.c src/libstddjb/djbtime-internal.h src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
-src/libstddjb/tai_now.o src/libstddjb/tai_now.lo: src/libstddjb/tai_now.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
+src/libstddjb/tai_now.o src/libstddjb/tai_now.lo: src/libstddjb/tai_now.c src/include/skalibs/tai.h
 src/libstddjb/tai_pack.o src/libstddjb/tai_pack.lo: src/libstddjb/tai_pack.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tai_pack_little.o src/libstddjb/tai_pack_little.lo: src/libstddjb/tai_pack_little.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
-src/libstddjb/tai_relative_from_timespec.o src/libstddjb/tai_relative_from_timespec.lo: src/libstddjb/tai_relative_from_timespec.c src/include/skalibs/tai.h
-src/libstddjb/tai_relative_from_timeval.o src/libstddjb/tai_relative_from_timeval.lo: src/libstddjb/tai_relative_from_timeval.c src/include/skalibs/tai.h
 src/libstddjb/tai_sub.o src/libstddjb/tai_sub.lo: src/libstddjb/tai_sub.c src/include/skalibs/tai.h
+src/libstddjb/tai_u64.o src/libstddjb/tai_u64.lo: src/libstddjb/tai_u64.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tai_unpack.o src/libstddjb/tai_unpack.lo: src/libstddjb/tai_unpack.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tai_unpack_little.o src/libstddjb/tai_unpack_little.lo: src/libstddjb/tai_unpack_little.c src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/tain_add.o src/libstddjb/tain_add.lo: src/libstddjb/tain_add.c src/include/skalibs/tai.h
@@ -598,8 +596,11 @@ src/libstddjb/tain_frac.o src/libstddjb/tain_frac.lo: src/libstddjb/tain_frac.c
 src/libstddjb/tain_from_localtmn.o src/libstddjb/tain_from_localtmn.lo: src/libstddjb/tain_from_localtmn.c src/include/skalibs/djbtime.h src/include/skalibs/tai.h
 src/libstddjb/tain_from_millisecs.o src/libstddjb/tain_from_millisecs.lo: src/libstddjb/tain_from_millisecs.c src/include/skalibs/tai.h
 src/libstddjb/tain_from_ntp.o src/libstddjb/tain_from_ntp.lo: src/libstddjb/tain_from_ntp.c src/include/skalibs/djbtime.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
+src/libstddjb/tain_from_sysclock.o src/libstddjb/tain_from_sysclock.lo: src/libstddjb/tain_from_sysclock.c src/include/skalibs/tai.h
 src/libstddjb/tain_from_timespec.o src/libstddjb/tain_from_timespec.lo: src/libstddjb/tain_from_timespec.c src/include/skalibs/tai.h
+src/libstddjb/tain_from_timespec_sysclock.o src/libstddjb/tain_from_timespec_sysclock.lo: src/libstddjb/tain_from_timespec_sysclock.c src/include/skalibs/tai.h
 src/libstddjb/tain_from_timeval.o src/libstddjb/tain_from_timeval.lo: src/libstddjb/tain_from_timeval.c src/include/skalibs/tai.h
+src/libstddjb/tain_from_timeval_sysclock.o src/libstddjb/tain_from_timeval_sysclock.lo: src/libstddjb/tain_from_timeval_sysclock.c src/include/skalibs/tai.h
 src/libstddjb/tain_half.o src/libstddjb/tain_half.lo: src/libstddjb/tain_half.c src/include/skalibs/tai.h
 src/libstddjb/tain_infinite_relative.o src/libstddjb/tain_infinite_relative.lo: src/libstddjb/tain_infinite_relative.c src/include/skalibs/tai.h
 src/libstddjb/tain_less.o src/libstddjb/tain_less.lo: src/libstddjb/tain_less.c src/include/skalibs/tai.h
@@ -618,18 +619,19 @@ src/libstddjb/tain_ulong.o src/libstddjb/tain_ulong.lo: src/libstddjb/tain_ulong
 src/libstddjb/tain_unpack.o src/libstddjb/tain_unpack.lo: src/libstddjb/tain_unpack.c src/include/skalibs/tai.h src/include/skalibs/uint32.h
 src/libstddjb/tain_unpack_little.o src/libstddjb/tain_unpack_little.lo: src/libstddjb/tain_unpack_little.c src/include/skalibs/tai.h src/include/skalibs/uint32.h
 src/libstddjb/tain_zero.o src/libstddjb/tain_zero.lo: src/libstddjb/tain_zero.c src/include/skalibs/tai.h
-src/libstddjb/timespec_from_tai.o src/libstddjb/timespec_from_tai.lo: src/libstddjb/timespec_from_tai.c src/include/skalibs/tai.h
-src/libstddjb/timespec_from_tai_relative.o src/libstddjb/timespec_from_tai_relative.lo: src/libstddjb/timespec_from_tai_relative.c src/include/skalibs/sysdeps.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
+src/libstddjb/time_from_tai.o src/libstddjb/time_from_tai.lo: src/libstddjb/time_from_tai.c src/include/skalibs/sysdeps.h src/include/skalibs/tai.h
+src/libstddjb/time_from_tai_relative.o src/libstddjb/time_from_tai_relative.lo: src/libstddjb/time_from_tai_relative.c src/include/skalibs/sysdeps.h src/include/skalibs/tai.h
+src/libstddjb/time_sysclock_from_tai.o src/libstddjb/time_sysclock_from_tai.lo: src/libstddjb/time_sysclock_from_tai.c src/include/skalibs/sysdeps.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/timespec_from_tain.o src/libstddjb/timespec_from_tain.lo: src/libstddjb/timespec_from_tain.c src/include/skalibs/tai.h
 src/libstddjb/timespec_from_tain_relative.o src/libstddjb/timespec_from_tain_relative.lo: src/libstddjb/timespec_from_tain_relative.c src/include/skalibs/tai.h
+src/libstddjb/timespec_sysclock_from_tain.o src/libstddjb/timespec_sysclock_from_tain.lo: src/libstddjb/timespec_sysclock_from_tain.c src/include/skalibs/tai.h
 src/libstddjb/timestamp.o src/libstddjb/timestamp.lo: src/libstddjb/timestamp.c src/include/skalibs/tai.h
 src/libstddjb/timestamp_fmt.o src/libstddjb/timestamp_fmt.lo: src/libstddjb/timestamp_fmt.c src/include/skalibs/tai.h
 src/libstddjb/timestamp_r.o src/libstddjb/timestamp_r.lo: src/libstddjb/timestamp_r.c src/include/skalibs/tai.h
 src/libstddjb/timestamp_scan.o src/libstddjb/timestamp_scan.lo: src/libstddjb/timestamp_scan.c src/include/skalibs/tai.h
-src/libstddjb/timeval_from_tai.o src/libstddjb/timeval_from_tai.lo: src/libstddjb/timeval_from_tai.c src/include/skalibs/tai.h
-src/libstddjb/timeval_from_tai_relative.o src/libstddjb/timeval_from_tai_relative.lo: src/libstddjb/timeval_from_tai_relative.c src/include/skalibs/sysdeps.h src/include/skalibs/tai.h src/include/skalibs/uint64.h
 src/libstddjb/timeval_from_tain.o src/libstddjb/timeval_from_tain.lo: src/libstddjb/timeval_from_tain.c src/include/skalibs/tai.h
 src/libstddjb/timeval_from_tain_relative.o src/libstddjb/timeval_from_tain_relative.lo: src/libstddjb/timeval_from_tain_relative.c src/include/skalibs/tai.h
+src/libstddjb/timeval_sysclock_from_tain.o src/libstddjb/timeval_sysclock_from_tain.lo: src/libstddjb/timeval_sysclock_from_tain.c src/include/skalibs/tai.h
 src/libstddjb/ucharn_findlen.o src/libstddjb/ucharn_findlen.lo: src/libstddjb/ucharn_findlen.c src/include/skalibs/fmtscan.h
 src/libstddjb/ucharn_fmt.o src/libstddjb/ucharn_fmt.lo: src/libstddjb/ucharn_fmt.c src/include/skalibs/fmtscan.h
 src/libstddjb/ucharn_fmt_little.o src/libstddjb/ucharn_fmt_little.lo: src/libstddjb/ucharn_fmt_little.c src/include/skalibs/fmtscan.h
diff --git a/package/info b/package/info
index d1a0dd0..7415877 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=skalibs
-version=2.1.0.0
+version=2.2.0.0
 category=prog
 package_macro_name=SKALIBS
diff --git a/src/include/skalibs/tai.h b/src/include/skalibs/tai.h
index 8a3f777..e411ff0 100644
--- a/src/include/skalibs/tai.h
+++ b/src/include/skalibs/tai.h
@@ -24,28 +24,26 @@ struct tai_s
 #define TAI_INFINITE { .x = TAI_MAGIC + ((uint64)1 << 61) }
 
 #define tai_sec(t) ((t)->x)
-#define tai_u64(t, u) ((void)((t)->x = (u)))
+extern int tai_u64 (tai_t *, uint64) ;
 #define tai_unix(t, u) tai_u64(t, (TAI_MAGIC + (u)))
 #define tai_uint(t, u) tai_u64(t, (uint64)(u))
 
-extern int tai_relative_from_timeval (tai_t *, struct timeval const *) ;
-extern int tai_from_timeval (tai_t *, struct timeval const *) ;
-extern int timeval_from_tai_relative (struct timeval *, tai_t const *) ;
-extern int timeval_from_tai (struct timeval *, tai_t const *) ;
+extern int tai_now (tai_t *) ;
 
-extern int tai_relative_from_timespec (tai_t *, struct timespec const *) ;
-extern int tai_from_timespec (tai_t *, struct timespec const *) ;
-extern int timespec_from_tai_relative (struct timespec *, tai_t const *) ;
-extern int timespec_from_tai (struct timespec *, tai_t const *) ;
+#define tai_relative_from_time(t, u) ((t)->x = (uint64)(u), 1)
+#define tai_from_time(t, u) tai_unix(t, u)
+#define tai_from_time_sysclock(t, u) tai_from_sysclock(t, (uint64)(u) + TAI_MAGIC)
+extern int time_from_tai_relative (time_t *, tai_t const *) ;
+extern int time_from_tai (time_t *, tai_t const *) ;
+extern int time_sysclock_from_tai(time_t *, tai_t const *) ;
 
-extern int tai_now (tai_t *) ;
 extern int tai_from_sysclock (tai_t *, uint64) ;
 extern int sysclock_from_tai (uint64 *, tai_t const *) ;
 
 #define tai_approx(t) ((double)(tai_sec(t)))
 
-extern void tai_add (tai_t *, tai_t const *, tai_t const *) ;
-extern void tai_sub (tai_t *, tai_t const *, tai_t const *) ;
+extern int tai_add (tai_t *, tai_t const *, tai_t const *) ;
+extern int tai_sub (tai_t *, tai_t const *, tai_t const *) ;
 #define tai_less(t,u) (tai_sec(t) < tai_sec(u))
 
 #define TAI_PACK 8
@@ -78,16 +76,22 @@ extern tain_t const tain_nano500 ;
 
 extern int tain_relative_from_timeval (tain_t *, struct timeval const *) ;
 extern int tain_from_timeval (tain_t *, struct timeval const *) ;
+extern int tain_from_timeval_sysclock (tain_t *, struct timeval const *) ;
 extern int timeval_from_tain_relative (struct timeval *, tain_t const *) ;
 extern int timeval_from_tain (struct timeval *, tain_t const *) ;
+extern int timeval_sysclock_from_tain (struct timeval *, tain_t const *) ;
 
 extern int tain_relative_from_timespec (tain_t *, struct timespec const *) ;
 extern int tain_from_timespec (tain_t *, struct timespec const *) ;
+extern int tain_from_timespec_sysclock (tain_t *, struct timespec const *) ;
 extern int timespec_from_tain_relative (struct timespec *, tain_t const *) ;
 extern int timespec_from_tain (struct timespec *, tain_t const *) ;
+extern int timespec_sysclock_from_tain (struct timespec *, tain_t const *) ;
 
 extern int sysclock_get (tain_t *) ;
 extern int tain_sysclock (tain_t *) ;
+extern int tain_from_sysclock (tain_t *, tain_t const *) ;
+extern int sysclock_from_tain (tain_t *, tain_t const *) ;
 #define tain_sysclock_g() tain_sysclock(&STAMP)
 extern int tain_clockmon_init (tain_t *) ;
 extern int tain_clockmon (tain_t *, tain_t const *) ;
@@ -106,12 +110,11 @@ extern double tain_frac (tain_t const *) gccattr_pure ;
 extern int tain_from_millisecs (tain_t *, int) ;
 extern int tain_to_millisecs (tain_t const *) gccattr_pure ;
 
-extern void tain_add (tain_t *, tain_t const *, tain_t const *) ;
+extern int tain_add (tain_t *, tain_t const *, tain_t const *) ;
 #define tain_add_g(deadline, tto) tain_add(deadline, &STAMP, tto)
-extern void tain_addsec (tain_t *, tain_t const *, int) ;
+extern int tain_addsec (tain_t *, tain_t const *, int) ;
 #define tain_addsec_g(deadline, n) tain_addsec(deadline, &STAMP, n)
-extern void tain_sub (tain_t *, tain_t const *, tain_t const *) ;
-extern void tain_half (tain_t *, tain_t const *) ;
+extern int tain_sub (tain_t *, tain_t const *, tain_t const *) ;
 extern int tain_less (tain_t const *, tain_t const *) gccattr_pure ;
 #define tain_future(deadline) tain_less(&STAMP, (deadline))
 
@@ -129,7 +132,8 @@ extern unsigned int tain_scan (char const *, tain_t *) ;
 extern unsigned int tain_fmtfrac (char *, tain_t const *) ;
 
 #define tain_uint(a, u) tain_ulong(a, u)
-extern void tain_ulong (tain_t *, unsigned long) ;
+extern int tain_ulong (tain_t *, unsigned long) ;
+extern void tain_half (tain_t *, tain_t const *) ;
 
 #define TIMESTAMP (1 + (TAIN_PACK << 1))
 extern unsigned int timestamp_fmt (char *, tain_t const *) ;
diff --git a/src/libstddjb/sysclock_from_localtmn.c b/src/libstddjb/sysclock_from_localtmn.c
index 7b227d2..a0ee34b 100644
--- a/src/libstddjb/sysclock_from_localtmn.c
+++ b/src/libstddjb/sysclock_from_localtmn.c
@@ -5,9 +5,7 @@
 
 int sysclock_from_localtmn (tain_t *a, localtmn_t const *l)
 {
-  uint64 u ;
-  if (!sysclock_from_localtm(&u, &l->tm)) return 0 ;
-  tai_u64(&a->sec, u) ;
+  if (!sysclock_from_localtm(&a->sec.x, &l->tm)) return 0 ;
   a->nano = l->nano ;
   return 1 ;
 }
diff --git a/src/libstddjb/sysclock_from_tai.c b/src/libstddjb/sysclock_from_tai.c
index 3db2640..3814bf2 100644
--- a/src/libstddjb/sysclock_from_tai.c
+++ b/src/libstddjb/sysclock_from_tai.c
@@ -1,5 +1,6 @@
 /* ISC license. */
 
+#include <errno.h>
 #include <skalibs/config.h>
 #include <skalibs/tai.h>
 
@@ -7,6 +8,7 @@
 
 int sysclock_from_tai (uint64 *u, tai_t const *t)
 {
+  if (t->x < 10U) return (errno = EINVAL, 0) ;
   *u = t->x - 10U ;
   return 1 ;
 }
diff --git a/src/libstddjb/sysclock_from_tain.c b/src/libstddjb/sysclock_from_tain.c
new file mode 100644
index 0000000..8a2bd12
--- /dev/null
+++ b/src/libstddjb/sysclock_from_tain.c
@@ -0,0 +1,10 @@
+ /* ISC license. */
+
+#include <skalibs/tai.h>
+
+int sysclock_from_tain (tain_t *u, tain_t const *t)
+{
+  if (!sysclock_from_tai(&u->sec.x, &t->sec)) return 0 ;
+  u->nano = t->nano ;
+  return 1 ;
+}
diff --git a/src/libstddjb/sysclock_from_utc.c b/src/libstddjb/sysclock_from_utc.c
index 25f9205..49228a7 100644
--- a/src/libstddjb/sysclock_from_utc.c
+++ b/src/libstddjb/sysclock_from_utc.c
@@ -1,5 +1,6 @@
 /* ISC license. */
 
+#include <errno.h>
 #include <skalibs/config.h>
 #include <skalibs/uint64.h>
 #include <skalibs/djbtime.h>
@@ -12,6 +13,7 @@ int sysclock_from_utc (uint64 *u)
 {
   tai_t t ;
   if (!tai_from_utc(&t, *u)) return 0 ;
+  if (t.x < 10) return (errno = EINVAL, 0) ;
   *u = t.x - 10 ;
   return 1 ;
 }
diff --git a/src/libstddjb/tai_add.c b/src/libstddjb/tai_add.c
index 91af283..ad481ea 100644
--- a/src/libstddjb/tai_add.c
+++ b/src/libstddjb/tai_add.c
@@ -2,7 +2,7 @@
 
 #include <skalibs/tai.h>
 
-void tai_add (tai_t *t, tai_t const *u, tai_t const *v)
+int tai_add (tai_t *t, tai_t const *u, tai_t const *v)
 {
-  tai_u64(t, tai_sec(u) + tai_sec(v)) ;
+  return tai_u64(t, tai_sec(u) + tai_sec(v)) ;
 }
diff --git a/src/libstddjb/tai_from_ltm64.c b/src/libstddjb/tai_from_ltm64.c
index 12a7394..0ecb49a 100644
--- a/src/libstddjb/tai_from_ltm64.c
+++ b/src/libstddjb/tai_from_ltm64.c
@@ -9,7 +9,7 @@ int tai_from_ltm64 (tai_t *t, uint64 u)
 {
   switch (skalibs_tzisright())
   {
-    case 1 : tai_u64(t, u + 10U) ; return 1 ;
+    case 1 : return tai_u64(t, u + 10U) ;
     case 0 : return tai_from_utc(t, u) ;
     default : return 0 ;
   }
diff --git a/src/libstddjb/tai_from_sysclock.c b/src/libstddjb/tai_from_sysclock.c
index c2bb546..087f353 100644
--- a/src/libstddjb/tai_from_sysclock.c
+++ b/src/libstddjb/tai_from_sysclock.c
@@ -7,8 +7,7 @@
 
 int tai_from_sysclock (tai_t *t, uint64 u)
 {
-  tai_u64(t, u + 10U) ;
-  return 1 ;
+  return tai_u64(t, u + 10U) ;
 }
 
 #else
diff --git a/src/libstddjb/tai_from_timespec.c b/src/libstddjb/tai_from_timespec.c
deleted file mode 100644
index e9fbe3e..0000000
--- a/src/libstddjb/tai_from_timespec.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* ISC license. */
-
-#include <sys/types.h>
-#include <time.h>
-#include <skalibs/tai.h>
-
-int tai_from_timespec (tai_t *t, struct timespec const *ts)
-{
-  tai_unix(t, ts->tv_sec) ;
-  return 1 ;
-}
diff --git a/src/libstddjb/tai_from_timeval.c b/src/libstddjb/tai_from_timeval.c
deleted file mode 100644
index 41cf5a1..0000000
--- a/src/libstddjb/tai_from_timeval.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* ISC license. */
-
-#include <sys/time.h>
-#include <skalibs/tai.h>
-
-int tai_from_timeval (tai_t *t, struct timeval const *tv)
-{
-  tai_unix(t, tv->tv_sec) ;
-  return 1 ;
-}
diff --git a/src/libstddjb/tai_from_utc.c b/src/libstddjb/tai_from_utc.c
index ba9cea9..c5dc62d 100644
--- a/src/libstddjb/tai_from_utc.c
+++ b/src/libstddjb/tai_from_utc.c
@@ -8,7 +8,5 @@
 int tai_from_utc (tai_t *t, uint64 u)
 {
   if (leapsecs_add(&u, 0) < 0) return 0 ;
-  u += 10 ;
-  t->x = u ;
-  return 1 ;
+  return tai_u64(t, u + 10) ;
 }
diff --git a/src/libstddjb/tai_now.c b/src/libstddjb/tai_now.c
index a1847ab..aaf388a 100644
--- a/src/libstddjb/tai_now.c
+++ b/src/libstddjb/tai_now.c
@@ -3,11 +3,11 @@
 /* MT-unsafe */
 
 #include <time.h>
-#include <skalibs/uint64.h>
 #include <skalibs/tai.h>
 
 int tai_now (tai_t *t)
 {
-  register uint64 u = TAI_MAGIC + time(0) ;
-  return tai_from_sysclock(t, u) ;
+  register time_t u = time(0) ;
+  if (u == (time_t)-1) return 0 ;
+  return tai_from_time_sysclock(t, u) ;
 }
diff --git a/src/libstddjb/tai_relative_from_timespec.c b/src/libstddjb/tai_relative_from_timespec.c
deleted file mode 100644
index 34bb555..0000000
--- a/src/libstddjb/tai_relative_from_timespec.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* ISC license. */
-
-#include <sys/types.h>
-#include <time.h>
-#include <skalibs/tai.h>
-
-int tai_relative_from_timespec (tai_t *t, struct timespec const *ts)
-{
-  tai_u64(t, ts->tv_sec) ;
-  return 1 ;
-}
diff --git a/src/libstddjb/tai_relative_from_timeval.c b/src/libstddjb/tai_relative_from_timeval.c
deleted file mode 100644
index f685da7..0000000
--- a/src/libstddjb/tai_relative_from_timeval.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* ISC license. */
-
-#include <sys/time.h>
-#include <skalibs/tai.h>
-
-int tai_relative_from_timeval (tai_t *t, struct timeval const *tv)
-{
-  tai_u64(t, tv->tv_sec) ;
-  return 1 ;
-}
diff --git a/src/libstddjb/tai_sub.c b/src/libstddjb/tai_sub.c
index d0c879e..e0cda7a 100644
--- a/src/libstddjb/tai_sub.c
+++ b/src/libstddjb/tai_sub.c
@@ -2,7 +2,7 @@
 
 #include <skalibs/tai.h>
 
-void tai_sub (tai_t *t, tai_t const *u, tai_t const *v)
+int tai_sub (tai_t *t, tai_t const *u, tai_t const *v)
 {
-  tai_u64(t, tai_sec(u) - tai_sec(v)) ;
+  return tai_u64(t, tai_sec(u) - tai_sec(v)) ;
 }
diff --git a/src/libstddjb/tai_u64.c b/src/libstddjb/tai_u64.c
new file mode 100644
index 0000000..a26d907
--- /dev/null
+++ b/src/libstddjb/tai_u64.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/uint64.h>
+#include <skalibs/tai.h>
+
+int tai_u64 (tai_t *t, uint64 u)
+{
+  if (u & ((uint64)1 << 63)) return (errno = EOVERFLOW, 0) ;
+  t->x = u ;
+  return 1 ;
+}
diff --git a/src/libstddjb/tain_add.c b/src/libstddjb/tain_add.c
index 6c6a237..aa6e705 100644
--- a/src/libstddjb/tain_add.c
+++ b/src/libstddjb/tain_add.c
@@ -2,13 +2,16 @@
 
 #include <skalibs/tai.h>
 
-void tain_add (tain_t *t, tain_t const *u, tain_t const *v)
+int tain_add (tain_t *t, tain_t const *u, tain_t const *v)
 {
-  tai_add(&t->sec, &u->sec, &v->sec) ;
-  t->nano = u->nano + v->nano ;
-  if (t->nano > 999999999U)
+  tain_t tt = *u ;
+  if (!tai_add(&tt.sec, &u->sec, &v->sec)) return 0 ;
+  tt.nano = u->nano + v->nano ;
+  if (tt.nano > 999999999U)
   {
-    t->nano -= 1000000000U ;
-    tai_u64(&t->sec, tai_sec(&t->sec)+1) ;
+    if (!tai_u64(&tt.sec, tai_sec(&tt.sec) + 1)) return 0 ;
+    tt.nano -= 1000000000U ;
   }
+  *t = tt ;
+  return 1 ;
 }
diff --git a/src/libstddjb/tain_addsec.c b/src/libstddjb/tain_addsec.c
index f4252a7..524ac20 100644
--- a/src/libstddjb/tain_addsec.c
+++ b/src/libstddjb/tain_addsec.c
@@ -2,19 +2,20 @@
 
 #include <skalibs/tai.h>
 
-void tain_addsec (tain_t *b, tain_t const *a, int c)
+int tain_addsec (tain_t *b, tain_t const *a, int c)
 {
-  b->nano = a->nano ;
   if (c >= 0)
   {
     tai_t t ;
-    tai_u64(&t, c) ;
-    tai_add(&b->sec, &a->sec, &t) ;
+    if (!tai_u64(&t, c)) return 0 ;
+    if (!tai_add(&b->sec, &a->sec, &t)) return 0 ;
   }
   else
   {
     tai_t t ;
-    tai_u64(&t, -c) ;
-    tai_sub(&b->sec, &a->sec, &t) ;
+    if (!tai_u64(&t, -c)) return 0 ;
+    if (!tai_sub(&b->sec, &a->sec, &t)) return 0 ;
   }
+  b->nano = a->nano ;
+  return 1 ;
 }
diff --git a/src/libstddjb/tain_from_ntp.c b/src/libstddjb/tain_from_ntp.c
index 6bf7697..5314a38 100644
--- a/src/libstddjb/tain_from_ntp.c
+++ b/src/libstddjb/tain_from_ntp.c
@@ -6,7 +6,7 @@
 
 int tain_from_ntp (tain_t *a, uint64 u)
 {
-  tai_t secs = { u >> 32 } ;
+  tai_t secs = { .x = u >> 32 } ;
   if (secs.x <= 0x7FFFFFFFUL) secs.x |= ((uint64)1 << 32) ;
   secs.x += TAI_MAGIC ;
   secs.x -= NTP_OFFSET ;
diff --git a/src/libstddjb/tain_from_sysclock.c b/src/libstddjb/tain_from_sysclock.c
new file mode 100644
index 0000000..468c248
--- /dev/null
+++ b/src/libstddjb/tain_from_sysclock.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/tai.h>
+
+int tain_from_sysclock (tain_t *a, tain_t const *u)
+{
+  if (!tai_from_sysclock(&a->sec, u->sec.x)) return 0 ;
+  a->nano = u->nano ;
+  return 1 ;
+}
diff --git a/src/libstddjb/tain_from_timespec.c b/src/libstddjb/tain_from_timespec.c
index e862f46..e471b95 100644
--- a/src/libstddjb/tain_from_timespec.c
+++ b/src/libstddjb/tain_from_timespec.c
@@ -1,13 +1,11 @@
 /* ISC license. */
 
-#include <sys/types.h>
 #include <time.h>
-#include <errno.h>
 #include <skalibs/tai.h>
 
-int tain_from_timespec (tain_t *a, struct timespec const *ts)
+int tain_from_timespec (tain_t *t, struct timespec const *ts)
 {
-  if (!tai_from_timespec(tain_secp(a), ts)) return 0 ;
-  a->nano = ts->tv_nsec ;
+  if (!tai_from_time(&t->sec, ts->tv_sec)) return 0 ;
+  t->nano = ts->tv_nsec ;
   return 1 ;
 }
diff --git a/src/libstddjb/tain_from_timespec_sysclock.c b/src/libstddjb/tain_from_timespec_sysclock.c
new file mode 100644
index 0000000..b79cda8
--- /dev/null
+++ b/src/libstddjb/tain_from_timespec_sysclock.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <time.h>
+#include <skalibs/tai.h>
+
+int tain_from_timespec_sysclock (tain_t *t, struct timespec const *ts)
+{
+  if (!tai_from_time_sysclock(&t->sec, ts->tv_sec)) return 0 ;
+  t->nano = ts->tv_nsec ;
+  return 1 ;
+}
diff --git a/src/libstddjb/tain_from_timeval.c b/src/libstddjb/tain_from_timeval.c
index 9c74d13..0536070 100644
--- a/src/libstddjb/tain_from_timeval.c
+++ b/src/libstddjb/tain_from_timeval.c
@@ -1,12 +1,11 @@
 /* ISC license. */
 
 #include <sys/time.h>
-#include <errno.h>
 #include <skalibs/tai.h>
 
-int tain_from_timeval (tain_t *a, struct timeval const *tv)
+int tain_from_timeval (tain_t *t, struct timeval const *tv)
 {
-  if (!tai_from_timeval(tain_secp(a), tv)) return 0 ;
-  a->nano = 1000 * tv->tv_usec ;
+  if (!tai_from_time(&t->sec, tv->tv_sec)) return 0 ;
+  t->nano = 1000 * tv->tv_usec ;
   return 1 ;
 }
diff --git a/src/libstddjb/tain_from_timeval_sysclock.c b/src/libstddjb/tain_from_timeval_sysclock.c
new file mode 100644
index 0000000..625c4cd
--- /dev/null
+++ b/src/libstddjb/tain_from_timeval_sysclock.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <sys/time.h>
+#include <skalibs/tai.h>
+
+int tain_from_timeval_sysclock (tain_t *t, struct timeval const *tv)
+{
+  if (!tai_from_time_sysclock(&t->sec, tv->tv_sec)) return 0 ;
+  t->nano = 1000 * tv->tv_usec ;
+  return 1 ;
+}
diff --git a/src/libstddjb/tain_half.c b/src/libstddjb/tain_half.c
index a95072e..4b8f404 100644
--- a/src/libstddjb/tain_half.c
+++ b/src/libstddjb/tain_half.c
@@ -4,7 +4,7 @@
 
 void tain_half (tain_t *t, tain_t const *u)
 {
-  t->nano = u->nano>>1 ;
-  if (tai_sec(&u->sec) & 1) t->nano += 500000000U ;
-  tai_u64(&t->sec, tai_sec(&u->sec)>>1) ;
+  t->nano = u->nano >> 1 ;
+  if (u->sec.x & 1) t->nano += 500000000U ;
+  t->sec.x = u->sec.x >> 1 ;
 }
diff --git a/src/libstddjb/tain_relative_from_timespec.c b/src/libstddjb/tain_relative_from_timespec.c
index e25793e..5f492ff 100644
--- a/src/libstddjb/tain_relative_from_timespec.c
+++ b/src/libstddjb/tain_relative_from_timespec.c
@@ -1,13 +1,11 @@
 /* ISC license. */
 
-#include <sys/types.h>
 #include <time.h>
-#include <errno.h>
 #include <skalibs/tai.h>
 
 int tain_relative_from_timespec (tain_t *a, struct timespec const *ts)
 {
-  if (!tai_relative_from_timespec(tain_secp(a), ts)) return 0 ;
+  tai_relative_from_time(&a->sec, ts->tv_sec) ;
   a->nano = ts->tv_nsec ;
   return 1 ;
 }
diff --git a/src/libstddjb/tain_relative_from_timeval.c b/src/libstddjb/tain_relative_from_timeval.c
index 83aa1c3..eafb57a 100644
--- a/src/libstddjb/tain_relative_from_timeval.c
+++ b/src/libstddjb/tain_relative_from_timeval.c
@@ -1,12 +1,11 @@
 /* ISC license. */
 
 #include <sys/time.h>
-#include <errno.h>
 #include <skalibs/tai.h>
 
 int tain_relative_from_timeval (tain_t *a, struct timeval const *tv)
 {
-  if (!tai_relative_from_timeval(tain_secp(a), tv)) return 0 ;
+  tai_relative_from_time(&a->sec, tv->tv_sec) ;
   a->nano = 1000 * tv->tv_usec ;
   return 1 ;
 }
diff --git a/src/libstddjb/tain_sub.c b/src/libstddjb/tain_sub.c
index f7dd4eb..2921aa6 100644
--- a/src/libstddjb/tain_sub.c
+++ b/src/libstddjb/tain_sub.c
@@ -2,14 +2,16 @@
 
 #include <skalibs/tai.h>
 
-void tain_sub (tain_t *t, tain_t const *u, tain_t const *v)
+int tain_sub (tain_t *t, tain_t const *u, tain_t const *v)
 {
-  tain_t uu = *u ;
-  tai_sub(&t->sec, &uu.sec, &v->sec) ;
-  t->nano = uu.nano - v->nano ;
-  if (t->nano > uu.nano)
+  tain_t tt = *u ;
+  if (!tai_sub(&tt.sec, &u->sec, &v->sec)) return 0 ;
+  tt.nano = u->nano - v->nano ;
+  if (tt.nano > u->nano)
   {
-    t->nano += 1000000000U ;
-    tai_u64(&t->sec, tai_sec(&t->sec)-1) ;
+    if (!tai_u64(&tt.sec, tai_sec(&tt.sec) - 1)) return 0 ;
+    tt.nano += 1000000000U ;
   }
+  *t = tt ;
+  return 1 ;
 }
diff --git a/src/libstddjb/tain_sysclock.c b/src/libstddjb/tain_sysclock.c
index 7f54db6..3b98eb1 100644
--- a/src/libstddjb/tain_sysclock.c
+++ b/src/libstddjb/tain_sysclock.c
@@ -6,7 +6,5 @@ int tain_sysclock (tain_t *a)
 {
   tain_t aa ;
   if (!sysclock_get(&aa)) return 0 ;
-  if (!tai_from_sysclock(&a->sec, aa.sec.x)) return 0 ;
-  a->nano = aa.nano ;
-  return 1 ;
+  return tain_from_sysclock(a, &aa) ;
 }
diff --git a/src/libstddjb/tain_ulong.c b/src/libstddjb/tain_ulong.c
index 2ba730a..8eb890b 100644
--- a/src/libstddjb/tain_ulong.c
+++ b/src/libstddjb/tain_ulong.c
@@ -2,8 +2,9 @@
 
 #include <skalibs/tai.h>
 
-void tain_ulong (tain_t *t, unsigned long s)
+int tain_ulong (tain_t *t, unsigned long s)
 {
-  tai_u64(&t->sec, s) ;
+  if (!tai_u64(&t->sec, s)) return 0 ;
   t->nano = 0 ;
+  return 1 ;
 }
diff --git a/src/libstddjb/time_from_tai.c b/src/libstddjb/time_from_tai.c
new file mode 100644
index 0000000..e03b8c5
--- /dev/null
+++ b/src/libstddjb/time_from_tai.c
@@ -0,0 +1,17 @@
+ /* ISC license. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <skalibs/sysdeps.h>
+#include <skalibs/tai.h>
+
+int time_from_tai (time_t *u, tai_t const *t)
+{
+  register uint64 uu = t->x - TAI_MAGIC ;
+#if SKALIBS_SIZEOFTIME < 8
+  if ((uu >> 32) && (uu >> 32) != 0xffffffffUL)
+    return (errno = EOVERFLOW, 0) ;
+#endif
+  *u = (time_t)uu ;
+  return 1 ;
+}
diff --git a/src/libstddjb/time_from_tai_relative.c b/src/libstddjb/time_from_tai_relative.c
new file mode 100644
index 0000000..f5233fe
--- /dev/null
+++ b/src/libstddjb/time_from_tai_relative.c
@@ -0,0 +1,16 @@
+ /* ISC license. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <skalibs/sysdeps.h>
+#include <skalibs/tai.h>
+
+int time_from_tai_relative (time_t *u, tai_t const *t)
+{
+#if SKALIBS_SIZEOFTIME < 8
+  if ((t->x >> 32) && (t->x >> 32) != 0xffffffffUL)
+    return (errno = EOVERFLOW, 0) ;
+#endif
+  *u = (time_t)t->x ;
+  return 1 ;
+}
diff --git a/src/libstddjb/time_sysclock_from_tai.c b/src/libstddjb/time_sysclock_from_tai.c
new file mode 100644
index 0000000..c16dbe2
--- /dev/null
+++ b/src/libstddjb/time_sysclock_from_tai.c
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <skalibs/sysdeps.h>
+#include <skalibs/uint64.h>
+#include <skalibs/tai.h>
+
+int time_sysclock_from_tai (time_t *u, tai_t const *t)
+{
+  uint64 uu ;
+  if (!sysclock_from_tai(&uu, t)) return 0 ;
+  uu -= TAI_MAGIC ;
+#if SKALIBS_SIZEOFTIME < 8
+  if ((uu >> 32) && (uu >> 32) != 0xffffffffUL)
+    return (errno = EOVERFLOW, 0) ;
+#endif
+  *u = (time_t)uu ;
+  return 1 ;
+}
diff --git a/src/libstddjb/timespec_from_tai.c b/src/libstddjb/timespec_from_tai.c
deleted file mode 100644
index 7bb84d4..0000000
--- a/src/libstddjb/timespec_from_tai.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* ISC license. */
-
-#include <sys/types.h>
-#include <time.h>
-#include <skalibs/tai.h>
-
-int timespec_from_tai (struct timespec *ts, tai_t const *t)
-{
-  tai_t trel ;
-  tai_u64(&trel, tai_sec(t) - TAI_MAGIC) ;
-  return timespec_from_tai_relative(ts, &trel) ;
-}
diff --git a/src/libstddjb/timespec_from_tai_relative.c b/src/libstddjb/timespec_from_tai_relative.c
deleted file mode 100644
index 42f2e95..0000000
--- a/src/libstddjb/timespec_from_tai_relative.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* ISC license. */
-
-#include <sys/types.h>
-#include <time.h>
-#include <errno.h>
-#include <skalibs/sysdeps.h>
-#include <skalibs/uint64.h>
-#include <skalibs/tai.h>
-
-int timespec_from_tai_relative (struct timespec *ts, tai_t const *t)
-{
-  if (tai_sec(t) >= (uint64)1 << 63) return (errno = EINVAL, 0) ;
-#if SKALIBS_SIZEOFTIME < 8
-  if (tai_sec(t) > 0xffffffffU) return (errno = ERANGE, 0) ;
-#endif
-  ts->tv_sec = (time_t)tai_sec(t) ;
-  ts->tv_nsec = 0 ;
-  return 1 ;
-}
diff --git a/src/libstddjb/timespec_from_tain.c b/src/libstddjb/timespec_from_tain.c
index 5eb6e30..cd63547 100644
--- a/src/libstddjb/timespec_from_tain.c
+++ b/src/libstddjb/timespec_from_tain.c
@@ -1,14 +1,11 @@
 /* ISC license. */
 
-#include <sys/types.h>
 #include <time.h>
 #include <skalibs/tai.h>
 
-int timespec_from_tain (struct timespec *ts, tain_t const *a)
+int timespec_from_tain (struct timespec *ts, tain_t const *t)
 {
-  struct timespec tmp ;
-  if (!timespec_from_tai(&tmp, tain_secp(a))) return 0 ;
-  ts->tv_sec = tmp.tv_sec ;
-  ts->tv_nsec = a->nano ;
+  if (!time_from_tai(&ts->tv_sec, &t->sec)) return 0 ;
+  ts->tv_nsec = t->nano ;
   return 1 ;
 }
diff --git a/src/libstddjb/timespec_from_tain_relative.c b/src/libstddjb/timespec_from_tain_relative.c
index 32e7993..8ef34e8 100644
--- a/src/libstddjb/timespec_from_tain_relative.c
+++ b/src/libstddjb/timespec_from_tain_relative.c
@@ -1,14 +1,11 @@
 /* ISC license. */
 
-#include <sys/types.h>
 #include <time.h>
 #include <skalibs/tai.h>
 
-int timespec_from_tain_relative (struct timespec *ts, tain_t const *a)
+int timespec_from_tain_relative (struct timespec *ts, tain_t const *t)
 {
-  struct timespec tmp ;
-  if (!timespec_from_tai_relative(&tmp, tain_secp(a))) return 0 ;
-  ts->tv_sec = tmp.tv_sec ;
-  ts->tv_nsec = a->nano ;
+  if (!time_from_tai_relative(&ts->tv_sec, &t->sec)) return 0 ;
+  ts->tv_nsec = t->nano ;
   return 1 ;
 }
diff --git a/src/libstddjb/timespec_sysclock_from_tain.c b/src/libstddjb/timespec_sysclock_from_tain.c
new file mode 100644
index 0000000..5544511
--- /dev/null
+++ b/src/libstddjb/timespec_sysclock_from_tain.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <time.h>
+#include <skalibs/tai.h>
+
+int timespec_sysclock_from_tain (struct timespec *ts, tain_t const *t)
+{
+  if (!time_sysclock_from_tai(&ts->tv_sec, &t->sec)) return 0 ;
+  ts->tv_nsec = t->nano ;
+  return 1 ;
+}
diff --git a/src/libstddjb/timeval_from_tai.c b/src/libstddjb/timeval_from_tai.c
deleted file mode 100644
index d0c4777..0000000
--- a/src/libstddjb/timeval_from_tai.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* ISC license. */
-
-#include <sys/time.h>
-#include <skalibs/tai.h>
-
-int timeval_from_tai (struct timeval *tv, tai_t const *t)
-{
-  tai_t trel ;
-  tai_u64(&trel, tai_sec(t) - TAI_MAGIC) ;
-  return timeval_from_tai_relative(tv, &trel) ;
-}
diff --git a/src/libstddjb/timeval_from_tai_relative.c b/src/libstddjb/timeval_from_tai_relative.c
deleted file mode 100644
index 94bd3f7..0000000
--- a/src/libstddjb/timeval_from_tai_relative.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* ISC license. */
-
-#include <sys/time.h>
-#include <errno.h>
-#include <skalibs/sysdeps.h>
-#include <skalibs/uint64.h>
-#include <skalibs/tai.h>
-
-int timeval_from_tai_relative (struct timeval *tv, tai_t const *t)
-{
-  if (tai_sec(t) >= (uint64)1 << 63) return (errno = EINVAL, 0) ;
-#if SKALIBS_SIZEOFTIME < 8
-  if (tai_sec(t) > 0xffffffffU) return (errno = ERANGE, 0) ;
-#endif
-  tv->tv_sec = (time_t)tai_sec(t) ;
-  tv->tv_usec = 0 ;
-  return 1 ;
-}
diff --git a/src/libstddjb/timeval_from_tain.c b/src/libstddjb/timeval_from_tain.c
index c780af7..2b4d577 100644
--- a/src/libstddjb/timeval_from_tain.c
+++ b/src/libstddjb/timeval_from_tain.c
@@ -3,11 +3,9 @@
 #include <sys/time.h>
 #include <skalibs/tai.h>
 
-int timeval_from_tain (struct timeval *tv, tain_t const *a)
+int timeval_from_tain (struct timeval *tv, tain_t const *t)
 {
-  struct timeval tmp ;
-  if (!timeval_from_tai(&tmp, tain_secp(a))) return 0 ;
-  tv->tv_sec = tmp.tv_sec ;
-  tv->tv_usec = a->nano / 1000 ;
+  if (!time_from_tai(&tv->tv_sec, &t->sec)) return 0 ;
+  tv->tv_usec = (t->nano + 500) / 1000 ;
   return 1 ;
 }
diff --git a/src/libstddjb/timeval_from_tain_relative.c b/src/libstddjb/timeval_from_tain_relative.c
index 624293c..de775fd 100644
--- a/src/libstddjb/timeval_from_tain_relative.c
+++ b/src/libstddjb/timeval_from_tain_relative.c
@@ -3,11 +3,9 @@
 #include <sys/time.h>
 #include <skalibs/tai.h>
 
-int timeval_from_tain_relative (struct timeval *tv, tain_t const *a)
+int timeval_from_tain_relative (struct timeval *tv, tain_t const *t)
 {
-  struct timeval tmp ;
-  if (!timeval_from_tai_relative(&tmp, tain_secp(a))) return 0 ;
-  tv->tv_sec = tmp.tv_sec ;
-  tv->tv_usec = a->nano / 1000 ;
+  if (!time_from_tai_relative(&tv->tv_sec, &t->sec)) return 0 ;
+  tv->tv_usec = (t->nano + 500) / 1000 ;
   return 1 ;
 }
diff --git a/src/libstddjb/timeval_sysclock_from_tain.c b/src/libstddjb/timeval_sysclock_from_tain.c
new file mode 100644
index 0000000..c41b133
--- /dev/null
+++ b/src/libstddjb/timeval_sysclock_from_tain.c
@@ -0,0 +1,11 @@
+/* ISC license. */
+
+#include <sys/time.h>
+#include <skalibs/tai.h>
+
+int timeval_sysclock_from_tain (struct timeval *tv, tain_t const *t)
+{
+  if (!time_sysclock_from_tai(&tv->tv_sec, &t->sec)) return 0 ;
+  tv->tv_usec = (t->nano + 500) / 1000 ;
+  return 1 ;
+}
diff --git a/src/libstddjb/utc_from_tai.c b/src/libstddjb/utc_from_tai.c
index f4d247e..80d2763 100644
--- a/src/libstddjb/utc_from_tai.c
+++ b/src/libstddjb/utc_from_tai.c
@@ -1,5 +1,6 @@
 /* ISC license. */
 
+#include <errno.h>
 #include <skalibs/uint64.h>
 #include <skalibs/tai.h>
 #include <skalibs/djbtime.h>
@@ -8,6 +9,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 ;
   *u = tt ;
   return 1 ;