Functions add/diff/cmp for xtime

Markus Kuhn Markus.Kuhn at cl.cam.ac.uk
Tue Oct 6 15:43:08 UTC 1998


Several commentors have expressed a desire to have a few basic
predefined arithmetic functions on xtime values.

I suggest to add the following three functions. These functions are so
simple that I feel the easiest way of specifying their behaviour is by
providing a sample implementation (i.e., using C as the specification
language instead of English):

------------------------------------------------------------------------
/*
 * Assertions:
 *
 * fabs(xtime_diff(xtime_add(t, d), t) - d) <= 0.5e-9
 *   for all t, d with fabs(t.sec + d) < 2**62 and t.nsec in the valid range
 *
 * xtime_cmp(xtime_add(t, d), t)
 *   is in the set {-1, 0, 1} and has the same sign as d or is 0 iff d==0.0
 *
 */


int xtime_cmp (struct xtime t1, struct xtime t2)
{
  if (t1.sec == t2.sec && t1.nsec == t2.nsec)
    return 0;
  if (t1.sec > t2.sec || (t1.sec == t2.sec && t1.nsec > t2.nsec))
    return 1;
  return -1;
}

double xtime_diff(struct xtime t1, struct xtime t2)
{
  if (t1.nsec > 1000000000) t1.nsec = 1000000000;
  if (t2.nsec > 1000000000) t2.nsec = 1000000000;

  return (t1.sec - t2.sec) + (t1.nsec - t2.nsec) / 1.0e9;
}

struct xtime xtime_add(struct xtime t, double d)
{
  double ds;

  if (t.nsec > 1000000000) t.nsec = 1000000000;

  t.nsec += floor(modf(d, &ds) * 1.0e9 + 0.5);
  t.sec  += ds;

  while (t.nsec >= 1000000000) t.sec++, t.nsec -= 1000000000;
  while (t.nsec <           0) t.sec--, t.nsec += 1000000000;

  return t;
}
------------------------------------------------------------------------

Note that concerning leap seconds, the arithmetic functions follow exactly
the spirit of the TIME_UTC definition and do not count inserted leap seconds
as time worth counting. So even if there is an inserted leap second

  1972-06-30 23:59:60 UTC

the xtime_diff difference between

  1972-06-30 00:00:00 UTC

and

  1972-07-01 00:00:00 UTC

is still precisely 86400.0 seconds. This allows you to use time
intervals such as 86400.0 in order to mean "one day later" on the UTC
clock, which is what most applications need (and what POSIX provided
so far).

Note that I also have carefully defined the behaviour of the function
for the case that they operate inside leap seconds to conform to this
model and to fulfil the - I think - desireable algebraic property that I
specified in the assertion.

If you are *really* interested in the number of SI seconds between two
UTC timestamps (very few applications will really need this, and those
usually will better use TIME_MONOTONIC instead of UTC), then just
convert both via xtime_conv() into TAI timestamps (assuming the
information is available), and then use xtime_diff on the resulting TAI
timestamps:

if (!xtime_conv(&tai1, TIME_TAI, &utc1, TIME_UTC) &&
    !xtime_conv(&tai1, TIME_TAI, &utc1, TIME_UTC))
  return xtime_diff(tai1, tai2);
else {
  /* relevant leap second history not available */
}


Very simple, very intuitive, very robust, very clear semantic,
and very straight forward.

*** I love it. ***

:-)


Other questions:

Has anyone made some experiments or can contribute arguments to decide
on whether passing 96-bit structs by pointer or by value is more desirable?

Has anyone completed the UTC part of the xtime_make() specification
code in the proposal or do I have to do this myself?

Is anyone willing to merge the xtime text with the existing C9X
draft and also include the change requests that Paul submitted
to ANSI?

Any suggestions regarding the sample code of the above functions?

Markus

-- 
Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
email: mkuhn at acm.org,  home page: <http://www.cl.cam.ac.uk/~mgk25/>




More information about the tz mailing list