# the ``need'' for POSIX times

Markus Kuhn Markus.Kuhn at cl.cam.ac.uk
Fri Oct 9 12:00:37 UTC 1998

```"D. J. Bernstein" wrote on 1998-10-08 17:15 UTC:
> Antoine Leca writes:
> > I just need to add 7*86400L to my start value.
>
> Is that actually guaranteed to work with Markus's library?

Yes, it is. That was the reason why some head scratching went into the
selection of how xtime_add() and xtime_diff() threat leap second values.

> Don't you get an invalid time if nsec starts out above 999999999?

No. Xtime_add first converts 23:59:60.1234 into 24:00:00 before
23:59:59.99999 and 24:00:00. This additional time is not available
when we go outside the leap second. So we first have to "conceptually"
shrink the borders of the leap second to a zero interval, and then
the original leap second timestamp gets trapped at 24:00:00 from where
you continue with normal arithmetic.

An alternative (probably much more intuitive) model of thought for the
same behaviour is the following: TIME_UTC does not count leap seconds as
real time. It ignores the time inserted by a leap second. Think of it in
the following Image: If you drive with your car along the timeline,
think of leap seconds as slippery intervals of the street of time where
they ignore the leap second. In this model of thought, xtime_add first
has to bring you out of the leap second, and then has to add the
required time interval in real non-leap time. If you start driving
inside a slippery leap second, your odometer doesn't start to count from
0 to 7*86400L before you have left the leap second.

If you visualize UTC arithmetic this way, it suddenly becomes very
intuitive (at least for me, try yourself).

This way, a lot of algebraic properites are nicely preserved by
xtime_add and xtime_diff. If they were defined on a single set (not
xtime + double), and if we ignore cosmological overflow, then they would
form proper group operations.

> > They (and I) want reliable and mostly straightforward ways to
> > resolve *their* problems, not trying to write convolutate
> > programs to handle the fantasy of Earth movement.
>
> With libtai the programmer simply says what he means:
>
>    caltime_utc(&ct,&sec,(int *) 0,(int *) 0); /* gmtime() */
>    ct.date.day += 7;
>    caltime_tai(&ct,&sec); /* mktime() */

With xtime, the programmer simply says what she means:

#define DAY 86400.0

the equivalent API will look even simpler because xtime_add becomes
of course function "+"(Left : Xtime; Right : Double) return Xtime:

t := t + 7 * DAY;

function "+"(Left : Xtime;        Right : Double)       return Xtime;
function "+"(Left : Xtime;        Right : Long_Integer) return Xtime;
function "+"(Left : Xtime;        Right : Xtime)        return Xtime;
function "+"(Left : Double;       Right : Xtime)        return Xtime;
function "+"(Left : Long_Integer; Right : Xtime)        return Xtime;

but for C this would probably be clumsy and overkill. The implementation
of those should be obvious from the xtime_add example.

> What exactly is ``convoluted'' about that? How has libtai ``impeded''
> time handling?

Beauty is in the eye of the beholder, but I reserve the right to
consider my code to be more straight forward. I also do not have to
define an equivalent of mktime() with overflow rules as you seem to
have, because I add always seconds directly. Look at the tmx proposal to
see how convoluted just the proper definition of mktime becomes in that case.
Code becomes difficult to read once people start to add months and years
via hidden overflow rules, as months and years differ in length. I would feel
highly uncomfortable by doing my time arithmetic via mktime()-like functions.
That was after all the whole reason for completely abandoning time_t in my
proposal.

> Markus's proposal is a disaster from the programmer's point of view.

Thank you for your honest opinion.

(Wait, so must be POSIX and BSD then, on which my proposal is *very*
closely modeled after all ...)

Markus

--
Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK