Proposal for new ISO C 9x time API

Paul Eggert eggert at twinsun.com
Wed Oct 7 08:45:06 UTC 1998


   From: Markus Kuhn <Markus.Kuhn at cl.cam.ac.uk>
   Resent-From: tz at elsie.nci.nih.gov

   The only doubts that I have about xtime is that I think it is with 96
   bits a bit too long. I would feel slightly better with 64 bits.

Yes, yes!  This is the Right Way to Go.  And we can do it, while still
satisfying your other concerns.

   It would also completely mess up the elegance of my API in that suddenly
   strfxtime and xtime_make/breakup would have to know from what type of
   clock this timestamp came.

strfxtime and the other primitives currently return garbage unless you
pass them a TIME_UTC timestamp.  I suppose one could argue that they
return well-defined garbage; but this well-defined garbage is useless
for practical applications.

This is a defect in the current proposal, and I plan to propose a fix
soon.  But no matter how it's fixed, it's inevitable that either (A)
time-zone-related primitives will have to know the timestamp's clock
type, or (B) such primitives will be useful only on TIME_UTC
timestamps.  (A) is better than (B), particularly if we adopt
solutions (2) and (3) mentioned below.

   > So I suggest that we give the programmer a way to access to the entire
   > leap second table known to the implementation.

   My API does this in form of tz_jump.

Yes, but I see that I wasn't clear.  Let me try to explain things
better.  I see three related problems with struct xtime in this area.

1.  The struct xtime spec makes it difficult for applications to
    detect bogus or unknown leap seconds.

    Suppose an application constructs a leap second timestamp (i.e. a
    struct xtime value with 1000000000<=nsec<2000000000), and passes
    this timestamp to an xtime primitive that expects a TIME_UTC
    timestamp.  Then the behavior is undefined unless the timestamp is
    not bogus (i.e. it is within a true inserted leap second) _and_
    the timestamp is known (i.e. the implementation knows about the
    leap second).  (The current spec doesn't say all this explicitly,
    but it certainly implies it.)

    Therefore, when importing a textual leap-second timestamp from the
    outside world, a struct xtime application can't blindly apply
    xtime_make and use the resulting value, as xtime_make might
    generate a bogus or unknown leap-second timestamp, which will
    cause problems when given to other primitives.  So the application
    needs a way to find out whether a purported leap second is a known
    leap second.  It can't pass the purported leap second directly to
    tz_jump, because if it's a bogus leap second tz_jump has undefined
    behavior.  I can think of hacky workarounds to this problem, but
    this is getting way too complicated; there ought to be a simpler
    way to attack this problem.

    One way to fix this particular problem would be to change the spec
    so that every primitive reports an error when given an bogus or
    unknown leap second.  This is an improvement, but it's not enough
    to address the other problems mentioned below; and solving the
    other problems will solve this problem.

2.  The struct xtime spec is an awkward interface to implementations
    based on TAI that do not have full leap second tables.

    Suppose implementation X internally uses a clock with TAI seconds,
    but it doesn't know the TAI epoch; that is, it knows the leap
    second or seconds within a window of a few months around the
    current time, and it knows the relationship between its internal
    clock and UTC within this window, but it doesn't know all the leap
    seconds back to 1972.  This seems to be the kind of implementation
    that is motivating your leap-second design, but I see a couple of
    problems with how struct xtime would interface to implementation X.

    First, implementation X can't support struct xtime's TIME_TAI, as
    this requires knowledge of the TAI epoch.  This seems backwards to
    me; fundamentally, the implementation is based on TAI not UTC, and
    it should have some way to report this to the application.

    Second, implementation X can't convert timestamps outside its
    window to internal format, so it will reject attempts to invoke
    primitives involving TIME_UTC timestamps outside its window, as
    the internal format of those timestamps would be undefined.  This
    seems counterintuitive to me.  From the user's point of view, we'd
    have a system that claims to support TIME_UTC but can't convert
    the out-of-window value 1970-01-01 00:00:00 UTC to a TIME_UTC
    timestamp, even though the result is perfectly well-defined to be
    zero (the problem being that the result's _internal form_ is
    unknown).

    A more natural way to support such an implementation is to have
    the struct xtime interface supply a generalization of TIME_TAI, one
    with an implementation-defined epoch.  This generalization would
    provide a more natural interface to this class of implementations,
    and would also support systems with complete knowledge of past leap
    seconds.

3.  The struct xtime spec does not support applications that do not
    want to know about leap seconds and do not ever want to see them.
    This is a large class of applications, and POSIX.1 (as well as
    many important non-POSIX OSes) support such applications, but the
    struct xtime spec doesn't support them at all.

    This can be fixed by adding a variant of TIME_UTC that never reports
    leap seconds.

If you combine solutions (2) and (3), then you don't need the current
TIME_UTC any more.  It's enough to have the generalization of TIME_TAI
with implementation-defined epoch, along with the variant of TIME_UTC
that never reports leap seconds.

Also, once you combine solutions (2) and (3), you don't ever need
struct xtime values with nsec>=1000000000.  If an application wants to
work properly with leap seconds, it should use the generalization of
TIME_TAI and thus doesn't need nsec>=1000000000.  Conversely, if the
application doesn't want to know about leap seconds and doesn't ever
want to see them, it should use the variant of TIME_UTC that never
reports leap seconds, so it also doesn't need nsec>=1000000000.

Disallowing nsec>=1000000000 simplifies things greatly.  It also makes
it practical to use a single 64-bit integer timestamp instead of a
two-part structure.

I'm working on a proposal along these lines (derived from your
proposal) and would like to publish it soon.



More information about the tz mailing list