Comments from David R Tribble on ISO C 9X time proposal

Here are a number of good comments on the modernized <time.h> from an author of a related proposal, which I'd like to share with those of you interested in this project. ------- Forwarded Message Date: Tue, 22 Sep 1998 15:11:31 -0500 To: Markus Kuhn <markus.kuhn@cl.cam.ac.uk> From: David R Tribble <david.tribble@dallas.beasys.com> Subject: new time.h comments I have some comments on your new <time.h> proposal. Some of these ideas came from my original proposal concerning an extended-precision time type (which I have abandoned for the time being; the text is still available at http://www.flash.net/~dtribble/text/c0xtime.htm if you're interested). 1. I would prefer that the macro names begin with an '_' in order to keep them out of the user's identifier name space. Thus, you would have names like '_TIME_UTC', '_TIME_TAI', etc. 2. It would be nice to have the concept of an 'unknown' or 'unspecified' time. Such a value would indicate a time value that is not (yet) known or a time value that has not (yet) been set to a valid time. This could be defined as a special constant named '_TIME_UNKNOWN'. Arithmetically, this value would compare less than all other valid time values. 3. Similarly, it would be nice to have the concept of a 'never' time, i.e., a time that has not yet occurred or a point in time that will never be reached. This could also be considered as something akin to a 'maximum' time value. This could be defined as a special constant named '_TIME_NEVER'. Arithmetically, this value would compare greater than all other valid time values. 4. You have defined the ability to determine the resolution of the time type, but there is no way to determine the valid range that time values span. This could be done by defining the macros '_TIME_MIN_YEAR' and '_TIME_MAX_YEAR' which specify, respectively, the earliest year containing Jan 1 and the latest year containing Dec 31, that are representable by the time type. 5. Of the 'TIME_XXX' macros defined, only the last three (TIME_LOCAL, TIME_SYNC, and TIME_RESOLUTION) need to be disjoint bitmask values; the remaining macro values can simply be distinct numeric values (such as 1, 2, 3, 4, etc.). (Personally, I don't like constants used for commands to include a zero value; zero to me means "undefined" or "unknown".) 6. The TIME_UTC epoch is defined as starting at 1970-01-01, but has no well-defined value until after 1972-01-01. Why not just define the epoch as beginning at 1972-01-01? 7. By the same token, the TIME_TAI epoch is defined as starting as 1970-01-01 but has no well-defined values until after 1972-01-01. Why not just start the epoch at 1972-01-01? 8. You need to be careful that, when describing the TIME_TAI epoch and times reckoned within that epoch, that you do not imply that such reckoning *requires* accuracy to external TAI time sources (i.e., make it clear that synchronization with outside time counters is purely optional.) Some people might misinterpret this as an implied requirement, and use it as justification to ignore your proposal. 9. The flaw with the TIME_TAI representation is that, even though single leap seconds are taken into account in the encoding, the difference between two TAI times does not properly account for the true number of leap seconds between them. Perhaps a function should exist for the sole purpose of deriving the difference between two (TAI) times which does take into account all intervening leap seconds, to wit: int diffxtime(struct xtime *diff, const struct xtime *a, const struct *xtime b); Fills in '*diff' with the difference between 'a' and 'b'. Returns i<0 if 'a' is before 'b', or i>0 if 'a' is after 'b', else 0. Perhaps an 'int clock_type' argument is needed, too. 10. The TIME_MONOTONIC epoch is defined as beginning at the last system reset. Some systems are not capable of discerning time this way, and can only reckon time from the start of the current process. Indeed, the standard clock() function is defined with this in mind. Perhaps the TIME_MONOTONIC epoch should be defined similarly. 11. TIME_PROCESS and TIME_THREAD fill a definite need, a la the times() call of POSIX. However, there is no way to ascertain the total elapsed CPU time for *child* processes. Perhaps a TIME_PROCESS_CHILDREN? 12. There ought to be a way to retrieve information for the local timezone. The definition of tz_prep() states that a null argument returns information about "some externally defined default timezone". A better definition would return information about "the local timezone, possibly determined from some external source (such as the program execution environment)". Alternatively, another function could be defined for the sole purpose of retrieving the local timezone information, such as: int tz_local(timezone_t *tz); 13. The calling convention to tz_prep() could be made better, to wit: int tz_prep(timezone_t *tz, const char *restrict tzstring); On success, the function shall set the contents of the object pointed to by 'tz' with the appropriate timezone information. This is better because tz_prep() does not then need to allocate any memory (it is allocated by the caller instead). This means that tz_free() is not needed. AFAIK, no standard library functions explicitly allocate memory, and the ISO committee has tried in the past to avoid inventing functions that do so. 14. The xtime_breakup() function ignores xtp->nsec, which is a shame. As I have suggested in other postings and in my proposal, it would be nice to have access to subsecond precision in the 'tm' structure, but this poses a problem with binary compatibility with existing code. What we are left with, then, is the need to access both the broken-down 'tm' structure and the original xtime value, so that we have access to the full time information. (On a tangent note, I don't like the name; perhaps something like xtime_split() or xtime_expand()?) 15. Similarly (as I have suggested previously), strftime() and strxftime() should contain a format specifier for fractional seconds (subseconds). Your proposal provides this ability. An alternative approach would be to add conversion specifiers for getting at the subseconds, such as: %q milliseconds (3 digits, not rounded) %Q microseconds (6 digits, not rounded) etc. (If conversion size specifiers are added, we would only need one specifier letter.) 16. In spite of your desire to obsolete the time_t type, we will still need a way of converting between xtime and time_t types, if for no other reason than for providing a smoother transition away from time_t. Without explicit conversion functions, the only alternative is to convert by first converting to struct 'tm' values, which seems unnecessarily wasteful. 17. I agree that the 'tmx' structure, with its tm_ext member, is an ill-conceived invention by the ISO committee. There ought to be a better way to allow for future extentions without the need for an extra allocation area. How this chunk is allocated, deallocated, and passed to other functions is never discussed in the draft. 18. You are slightly incorrect about Microsoft using a float type for time_t; they use a 32-bit signed binary integer identical to the POSIX time_t type. Apple's Rhapsody O/S, however, uses a 'double' for times and intervals. 19. Minor typos: 1.2.1, xtime_get(), "Returns": <If time != NULL then> should be <If xtp != NULL then>. 1.4.4, strfxtime(), "Description": <full stop> should be <period>; <decimal dot or decimal comma> should be <decimal-point period or comma>, see wording in [7.11.2.1 localeconv()] for consistency. 2, Rationale, "Lack of control over timezone": <proofed> should be <proved>. 2, Rationale, "POSIX and BSD predecessors": <problematic> should be <problem>. One final suggestion, pertaining to your choice of representation for the xtime type: You might want to consider implementing the xtime type as a 64-bit signed binary integer value instead of a structure. Either 'long long int' or 'int_least64_t' would be appropriate, with the value of a given time t is: t = (sec x 2 x 10^6) + usec + (Lsec x 10^6) where 'sec' is the number of seconds since the start of the epoch, 'usec' is the number of microseconds since that second, and 'Lsec' is 1 if a leap second is present, otherwise it is 0. This encoding seems to accomplish the same goals as your xtime structure, with the advantage that, since it is a simple arithmetic type, computations can be performed on it more efficiently. And it is smaller than the structure (64 bits wide instead of 96). These make it more amenable for directly storing it in binary data files and transmitting across networks. Even though it has less high bits, it is still capable of representing time to the nearest microsecond across a range of over 146,000 years (BC73000 to AD73000), which should be quite sufficient for most applications. The only real difference between this type and your xtime type is the resolution; I think that microsecond precision would be useful for most applications. (Of course, we could push the resolution up by a factor of ten, encoding 100 nsec ticks instead of usecs, which would reduce the range down to BC7300-AD7300, or BC4713-AD9900.) I hope these comments help. I, too, am quite serious about getting a useful and "correct" set of time/date functions into the new C9X standard. I am in the process of feeding my suggestion to Clive Feather, who has expressed an interest in collecting such comments and rewriting section 7.23 of the C9X draft. --------------------. +1-972-738-6125 Work ,-. C++: the PL/1 of David R. Tribble \ ,---------------------' \ the 90s http://www.beasys.com `-' +1-972-738-6111 Fax `------------------- dtribble@technologist.com http://www.flash.net/~dtribble Support the anti-Spam amendment, join at http://www.cauce.org/ ------- End of Forwarded Message

David Tribble (via Markus Kuhn) wrote:
11. TIME_PROCESS and TIME_THREAD fill a definite need, a la the times() call of POSIX. However, there is no way to ascertain the total elapsed CPU time for *child* processes. Perhaps a TIME_PROCESS_CHILDREN?
Does ISO C now have a notion of processes or threads, or children?
12. There ought to be a way to retrieve information for the local timezone. The definition of tz_prep() states that a null argument returns information about "some externally defined default timezone". A better definition would return information about "the local timezone, possibly determined from some external source (such as the program execution environment)".
The objection here is "Local to whom"? The physical location of a computer is becoming less and less significant. If I'm in Alabama, do I care what a server in Georgia (the Republic of) thinks "the" time is? -- John Cowan http://www.ccil.org/~cowan cowan@ccil.org You tollerday donsk? N. You tolkatiff scowegian? Nn. You spigotty anglease? Nnn. You phonio saxo? Nnnn. Clear all so! 'Tis a Jute.... (Finnegans Wake 16.5)
participants (2)
-
John Cowan
-
Markus Kuhn