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