big-picture comments on your proposed extensions to ISO C <time.h>

Paul Eggert eggert at twinsun.com
Wed Sep 30 21:44:01 UTC 1998


   Date: Wed, 30 Sep 1998 16:01:33 +0200
   From: Antoine Leca <Antoine.Leca at renault.fr>

   Paul Eggert wrote, discussing with Markus:

   >    >   let's just use a signed integer count of the number of time
   >    >   intervals since the epoch. We can define a type stime_t for this
   >    >   integer, and a stime_t macro STIMES_PER_SEC giving the number of
   >    >   time intervals per second.  This makes time arithmetic much, much
   >    >   easier.

   Hmm. I am not sure to follow you here, since for the vast majority of
   applications, struct xtime arithmetic will be defined as following

   struct xtime addxtime(struct xtime x, struct xtime y) {
     return (struct xtime){.sec = x.sec+y.sec};
   }

But this gives an answer that can be off by as much as two seconds;
an inaccuracy like that would break many applications.

Your remark reinforces my impression that the struct xtime method is
too error-prone in practice.

   This proposal have a clear drawback: like clock_t in C89, it
   requires to specify the resolution of the type itself requiring a
   lot of multiplication/division with a constant like XTIME_PER_SEC

But any time proposal must specify the resolution somehow.  struct
xtime specifies it as nanoseconds, for example; so there is an implied
XTIME_PER_SEC value of 1000000000.  I don't see this as a special
drawback of my proposal.

   *if* we disregard subseconds, Markus' proposal is essentialy the
   same as the initial POSIX, isn't it?

Yes; but that's also true for my proposal.  If STIMES_PER_SEC is 1,
then it degenerates to the original POSIX.1 as a special case.

   Another idea is striking me right now:
    - keeping struct xtime
    - specifying that the first member, named sec, typed int_fast64_t, should
      be what it is now with Markus' draft
    - allowing others fields, providing they are self-containing, for
      counting more precise quantities
    - adding to the draft addxtime, diffxtime, mulxtime, divxtime
    - adding to the draft a way to convert from double to xtime and back,
      either with an API (well, two), or with a macro giving the precision
      or any subfield.
   What about this sketch?

Something like that could be done, but it is complicated; if you're
going to have that level of complexity, you might as well make
struct xtime be an opaque type (xtime_t, say) and be done with it.

That way, I could define xtime_t to be a signed integer value, and
Markus could make it a structure.  This would be a reasonable
committee-like compromise that might satisfy neither of us (:-).

In practice, though, I hope that the signed-integer-value approach
would win out, as it is so much more convenient to use; much as the
POSIX.1 time_t won out over the C89 opaque time_t.

   >    How would you represent leap seconds in your stime_t arithmetic type?
   > 
   > The most natural approach is to have xtime_get (or a variant) return a
   > boolean flag specifying whether the timestamp is within a leap second.
   > This would be needed only with TIME_UTC timestamps.

   This way way, we should add a parameter to both xtime_make and
   xtime_breakup: either an input argument, or an output one.

Yes, this would be needed if we use a separate boolean.

   Furthermore, there should be some way for xtime_breakup to disambiguate
   between UTC and TAI: so one more parameter...

I don't understand this comment.  xtime_breakup is defined to work
only on TIME_UTC timestamps.  There's no need to break up TIME_TAI
timestamps.


   >    For stime_get however this is not an option: the return value is
   >    certainly required for comfortable error checking.
   > 
   > No, you can return a negative number -E such that E is suitable as an
   > argument to strerror.  This is a natural way to report errors for many
   > of the xtime functions.

   Yes, but it should not be *required* to be done this way: the Committee
   have strong feeling against standardizing this way, since errno-mechanism
   is very problematic to be used in some environments (this was tolerated
   for math.h because of wide existing practice).

The approach that I'm suggesting does not use errno -- it returns a
value suitable as an argument to strerror, without communicating it
via errno.  So I think the suggestion shouldn't run afoul of the
anti-errno sentiment.

   > It's that sense in which struct xtime is not a completely portable
   > type; you can't output it from one implementation and read it back
   > into another, even in textual form, without possibly having some
   > problems.

   In textual form, I do not see the problem. What is wrong with

     fprintf(output, PRIdFAST64 ":" PRIdFAST32 "\n", xt.sec, xt.nsec);
   then
     fscanf  (input, SCNdFAST64 ":" SCNdFAST32 "\n", xt.sec, xt.nsec);

That code doesn't report overflow well if the destination host's sec
field is smaller than the source's.

However, my comments were about binary I/O.  If you're willing to go
to textual form, then the signed integer approach is also portable,
though I admit that it's a bit trickier, as you must also output the
resolution.


   > I don't think the Olson-style names should be required; but they
   > should be suggested, at least in a footnote with a URL.

   This is not standard practice in the text of an ISO Standard (I think
   this is even prohibited).

Wow, an ISO standard can't say ``should''?  OK, if so, the Rationale
would be fine.

   > That doesn't work in the presence of leap seconds.

   Yes it does (using Markus' acceptation of xtime)...
   unless of course you are referring to the point I avoided above, that
   is if the beginning point was in a leap second.

Sorry, I should have been clearer.  You are correct: adding 3 * 86400
to the sec field doesn't work if the starting timestamp is within a
leap second.

Also, even ignoring the problem of starting within a leap second,
there is a difference between wanting a time that is 3*86400 seconds
later, and wanting a time that is 3 days later, because the former
wants to respect leap seconds but the latter wants to ignore them.

C89 mktime supports both sorts of requests (assuming int is large
enough to represent 3*86400) but the struct xtime proposal supports
only the latter.

Or perhaps the intent is that if you want to add 3*86400 seconds then
you have to convert your TIME_UTC timestamp to some other clock type,
do the arithmetic there, and then convert back?  If so, which clock
type is recommended?  TIME_TAI would be the best, but presumably it's
not always available.  So I'm a bit puzzled if this is indeed the
intent.

   > there is still one value that is quite
   > inconvenient to get via strftime: the UTC offset (to the nearest
   > second, please! :-).  Perhaps a new format spec could be added to get that?

   I think this should be left to the programmer, using first strfxtime("%z"...),
   then parsing the result and multiplying the hour count by 3600, the minute
   count by 60.

That is inconvenient, but it would work, so long as %Z outputs the UTC
offset to 1-second resolution if necessary, not just the 1-minute in
the current proposal.



More information about the tz mailing list