The new ISO C draft is on <ftp://dkuug.dk/JTC1/SC22/wg14/index.html>. I think, the following message might be of great interest to many here. I hope Clive has in the meantime managed to join the tz list, such that we can discuss proposals here. Markus ------- Forwarded Message From: "Clive D.W. Feather" <clive@demon.net> Subject: It's about time [sorry for the bad joke] I'm sorry I've taken so long to get back to people about this. This email is going to all the people who have expressed to me an interest in the C9X time functions. C9X CD2 (aka the FCD) is now published (it can be found on the DKUUG web site). It basically contains the same material in <time.h> as CD1 did, though a few minor errors have been corrected and Keld's %O and %E modifiers have appeared. Everyone who's written to me has expressed dissatisfaction with some part or other of the current situation. Therefore I have a rather radical proposal to make: I suggest we write a complete new <time.h> section that addresses all our issues, and arrange for at least two, and preferably three or more, National Bodies to submit it as part of their response to CD2. I'm willing to act as the core editor for this work, provided: - people will write full pieces of text for me to drop in as needed; - people won't object to my use of editorial powers to tidy up and keep the wording consistent. I can provide web space where I will keep the working drafts. I suggest we start with what's in CD2 as a common base, though being ready to drop pieces if that's what we agree. In the meantime, here's all the issues that I'm aware of that our text would need to handle: (1) Clear definition of canonicalisation of times. (2) Unambigous mechanisms for converting between UTC and TAI, and between time zones, and for determining which is in use. (3) Clearer definitions of things like strftime conversions (all of these are in CD2, so this is a no-op). (4) Ability to determine the precision of times (a ticks per second macro, perhaps). This should be guaranteed to be <= 1 second over some range. (5) Ability to determine the range of time_t, with guaranteed minimum limits. (6) A member in struct tmx for access to subsecond resolution, and possibly new formats to access it. (7) The meaning of struct tm to remain source and binary compatible with C89. (8) Clearer definition of what struct tm[x] values must be handled by implementations. (9) All new functions to be re-entrant. (10) Rethink future expandibility of struct tmx. (11) Portable form for transferring time values between programs and implementations. Anything else ? I've no objection to this message having wider circulation, but only to people who aren't going to require more education than there's time for. -- Clive D.W. Feather | Regulation Officer, LINX | Work: <clive@linx.org> Tel: +44 1733 705000 | (on secondment from | Home: <cdwf@i.am> Fax: +44 1733 353929 | Demon Internet) | <http://i.am/davros> ------- End of Forwarded Message
For a variety of reasons I've been building my own date-time library, supporting five basic data types: * Calendar dates. ``struct caldate'' contains year, month, day. You can convert to and from YYYY-MM-DD strings for data interchange. * Day numbers. You can convert between calendar dates and MJD. This makes date arithmetic very easy for calendar programs. * Civil times. ``struct caltime'' contains date, hour, minute, second, and time-zone offset in minutes. You can convert to and from YYYY-MM-DD HH:MM:SS +OOOO strings for data interchange. * 1-second timestamps. ``struct tai'' stores a 64-bit real-time counter with a range of hundreds of billions of years. You can convert timestamps to and from a portable 8-byte format, defined in http://pobox.com/~djb/proto/tai64.txt, for storage or interchange. * 1-attosecond timestamps. ``struct taia'' stores a real-time counter, a nanosecond counter, and an attosecond counter. You can convert timestamps to and from a portable 16-byte format. See http://pobox.com/~djb/libtai.html for the latest version. ---Dan
On Thu, 3 Sep 1998, Markus Kuhn wrote (quoting Clive Feather):
(9) All new functions to be re-entrant.
As noted before on this list: this means that timezones should be explicit parameters, and new functions should not have implicit dependence on the local timezone, though they may have such dependence on the locale. However the re-entrant functions from POSIX should maybe still be included despite not having explicit timezone parameters (ctime_r, localtime_r).
Anything else ?
Some more points that need to be covered: *) Allowing conforming implementations both with and without leapsecond tables. *) Retaining compatibility with systems on which time_t does not allow for leapseconds, as well as those on which it does, while still allowing those on which it doesn't allow for leapseconds (e.g. POSIX) to have leapsecond support and TAI<->UTC conversions through new interfaces. *) Allowing for real timezones (presumably through compiling timezone descriptions from a TZ string which could represent a POSIX timezone or an implementation extension beginning with ':'). -- Joseph S. Myers jsm28@cam.ac.uk
I think, I have come up with a nice C API that fulfills all the stated requirements. At the moment, it is just a first design sketch, not something that could already be pasted into ISO C, but please have a look at it and think about whether you would like this <xtime.h> to become the successor of the quite broken <time.h>. The API below have fewer functions and yet provides much more functionality than <time.h>. I think that the approach below is more practical that Dan Bernstein's completely TAI-based API. My API does not require any leapsecond history to be stored in the system, something which I would never expect to be updated reliably in practice. 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/> // // <xtime.h> // // Proposal for a modern time and calendar API for ISO C 9x - first sketch // // Markus Kuhn <mkuhn@acm.org> -- 1998-09-04 // // Note: The names of objects are not yet final and have likely to be // changed for backwards compatibility reasons. // The <xtime.h> API is added to the existing <time.h>. The old // <time.h> is not modified, maintained for backwards compatibility, // and declared deprecated. The old <time.h> can be implemented // completely on top of the the <xtime.h> functions. // #include <stdint.h> // arithmetic time (replacing both time_t and clock_t, on POSIX systems // often bit compatible with struct timespec) struct xtime { int_fast64_t sec; // seconds since the epoch int_fast32_t nsec; // nanoseconds [0, 1_999_999_999] }; // query the clock(s) #define TIMEOPT_UTC 1 #define TIMEOPT_TIA 2 #define TIMEOPT_LOCAL 4 #define TIMEOPT_SYNC 8 #define TIMEOPT_MONOTONIC 16 #define TIMEOPT_PROCESS 32 #define TIMEOPT_THREAD 64 void get_xtime(struct xtime *time, int *options); /* Function get_xtime(&time, &options) queries the clock and writes one * form of time into *time. The variable *options specifies which form of * time is requested and contains after the call some status bits that * indicate properties of the form of time that has been returned. * * The possible properties are: * * TIMEOPT_UTC the epoch is 1970-01-01 00:00:00 UTC and time->sec * does not count inserted leap seconds and did count * removed leap seconds as if they hadn't been removed. * During a leap second (if the implementation is aware * of it), time->sec shows the value for the previous * second and time->nsec continues to increase in the * range 1e9 .. 2e9-1. * * TIMEOPT_TAI the epoch is 1970-01-01 00:00:00 TAI and time->sec * does count inserted leap seconds and does not count * removed leap seconds. time->nsec < 1_000_000_000. * * TIMEOPT_LOCAL the epoch is 1970-01-01 00:00:00 in the local time * zone. This is only a fallback option for systems * that are ignorant of UTC and know nothing but some * local time. TIMEOPT_LOCAL need not be supported on * systems that support TIMEOPT_UTC. * * TIMEOPT_SYNC Can appear only together with TIMEOPT_UTC and * TIMEOPT_TAI and indicates that the system has so * frequently been synchronized with an official time * source such that with high probability the deviation * from UTC resp. TAI is less than 1 s. * * TIMEOPT_MONOTONIC The time comes from a clock with the following * property: If A and B are readings taken from this * clock (in seconds since the epoch) and TA and TB are * the corresponding TIMEOPT_TAI readings, then * 1-1/2000 < (A-B)/(TA-TB) < 1+1/2000. In other words, * the frequency of a monotonic clock is never off * more than 500 ppm, a target that cheap clock oscillators * in office equipment can easily guarantee. This clock * cannot be reset while the process is running and * it will never show a leap second: time->nsec < * 1_000_000_000. TIMEOPT_MONOTONIC is guaranteed to be * always available. * * TIMEOPT_PROCESS The epoch is the start of this process and the * measured time is the CPU time consumed by this process * so far. TIMEOPT_PROCESS is guaranteed to be always * available. * * TIMEOPT_THREAD The epoch is the start of this thread and the * measured time is the CPU time consumed by this thread * so far. TIMEOPT_PROCESS is guaranteed to be always * available. On systems without multithreading, * we always have TIMEOPT_THREAD == TIMEOPT_PROCESS. * * The status bits TIMEOPT_UTC, TIMEOPT_TAI, and TIMEOPT_LOCAL * are mutually exclusive. TIMEOPT_SYNC can only appear together with * TIMEOPT_UTC and TIMEOPT_TAI. * * The variable *options is used by the caller to select what type of * clock is requested, by specifying one of TIMEOPT_UTC, TIMEOPT_TAI, * TIMEOPT_MONOTONIC, TIMEOPT_PROCESS, or TIMEOPT_THREAD in the value * provided to get_time(). The caller then has to check in the returned * options variable, whether the bit is still set to find out whether * the required time was known. * * The TIMEOPT_MONOTONIC value can at boot time be equivalent with any * of the other clocks, but it can also have its epoch at boottime. * TIMEOPT_MONOTONIC, TIMEOPT_PROCESS, and TIMEOPT_THREAD are the only * clocks guaranteed to be available on all implementations. * * If a TIMEOPT_MONOTONIC value is given to mkxtm, the resulting * broken-down time might not be very meaningful. If TIMEOPT_LOCAL * is given to mkxtm, then zonespec should be TZ_UNDEFINED such that * the xtm value reflects that the precise epoch is not known. * * Implementation example: * * A typical desktop system will have only TIMEOPT_UTC, * TIMEOPT_MONOTONIC, TIMEOPT_PROCESS, and TIMEOPT_THREAD available. * After boot, we will have TIMEOPT_UTC == TIMEOPT_MONOTONIC until * someone adjusts the system clock. TIMEOPT_MONOTONIC will not be * affected by this adjustment, TIMEOPT_UTC will be a best effort * estimate of UTC. If the system has a leap seconds file that is less * than 6 months old or is connected to a GPS receiver, then * TIMEOPT_TAI might also be available. Note that systems have no need * to store the leap second history, because no function of this API * allows to convert between UTC and TAI. * * TIMEOPT_LOCAL need not be available on systems that have * TIMEOPT_UTC. Local time should preferably be determined by * specifying TZ_DEFAULT or the respective local time zone to * mkxtm. * * Systems without a battery clock will not have TIMEOPT_UTC available * after boot time, but TIMEOPT_MONOTONIC can already be used to make * time measurements and can also be used to backdate timestamps that * were made before UTC became known (e.g., by a network communication * or a radio clock lock-on). * */ // internal efficient representation of a time zone rule typedef struct { ... } timezone_t; // generate a timezone_t description from a string (e.g., POSIX.1 TZ format // or Olsen database entry, or ...). Return *zone = NULL if there is // some syntax error in the string. void prepare_timezone(timezone_t **zone, char *zonespec); // free the time zone descriptor zone and set *zone == TZ_UTC to remove // dangling pointers void free_timezone(timezone_t **zone); // some predefined time zone descriptors #define TZ_UTC (timezone_t *) 0 #define TZ_UNDEFINED (timezone_t *) -1 #define TZ_DEFAULT (timezone_t *) -2 // eg. from environment var TZ, etc. /* When we use mkxtm() to split a xtime value up into a calendar date * and a hhmmss time (struct xtm), then we have to specify in which * time zone this time should be. If we are happy with UTC, we specify * TZ_UTC, and we will get offset==0. If the xtime value is not an * approximation of a UTC timestamp, then we specify TZ_UNDEFINED, * which indicates in struct tmx that offset is meaningless. If we * want to have whatever the system sees as its default or local time * zone, then we specify TZ_DEFAULT. We can select any other time zone * by parsing a time zone description with timezone() and specifying * the result. */ // brocken down date and time struct xtm { long nsec; // nanoseconds after the second [0, 999_999_999] int sec; // seconds after the minute [0, 60] int min; // minutes after the hour [0, 59] int hour; // hours since midnight [0, 23] int mday; // day of the month [1, 31] int mon; // months since December [Jan=1, Dec=12] int year; // number of the year int wday; // days since Sunday [Mon=1, Sun=7] int week; // calendar week number (ISO 8601) [1, 53] int wyear; // year of the current week (ISO 8601) int yday; // days since December 31 [1, 366] int offset; // minutes east off UTC int repeat; // flag indicating first hour after DST timezone_t *zone; // time zone descriptor }; /* * Note that in xtm, leap seconds are indicated by sec==60 and not by * and nsec overflow. */ // display a brocken down time size_t strfxtime(char * restrict s, size_t maxsize, const char * restrict format, const struct xtm * restrict timeptr); // construct a xtime value from a broken down date and time (return -1 // on error, 0 else) int mkxtime(const struct xtm *src, struct xtime *dest); // construct a brocken down date/time representation from an xtm value // (return -1 on error, 0 else) int mkxtm(const struct xtime *src, const timezone_t *zone, struct xtm *dest); /* * In time zones with summer time switches, the first hour of winter time * repeats the time values of the previous hour. To distinguish these values * the flag repeat is set to one. (May be, we can also keep the old DST * flag here instead) * * In the tmx given to mkxtime, only the components nsec, sec, min, * hour, mday, mon, year, offset, repeat, and zone are examined. The * values of the other components are irrelevant. Values that are out * of range in nsec, sec, min, hour, mday, mon, year are adjusted * accordingly, for instance if sec is negative, then 60 is added to * sec while 1 is subtracted from min until the value is in the * correct interval before conversion takes place. If zone == * TZ_UNDEFINED, then mkxtime behaves exactly as if TZ_UTC. */
On Fri, 4 Sep 1998, Markus Kuhn wrote:
I think, I have come up with a nice C API that fulfills all the stated requirements. At the moment, it is just a first design sketch, not something that could already be pasted into ISO C, but please have a look at it and think about whether you would like this <xtime.h> to become the successor of the quite broken <time.h>. The API below have fewer functions and yet provides much more functionality than <time.h>.
This seems like a reasonably clean solution - some comments are below.
// The <xtime.h> API is added to the existing <time.h>. The old // <time.h> is not modified, maintained for backwards compatibility, // and declared deprecated. The old <time.h> can be implemented // completely on top of the the <xtime.h> functions.
I would say there should be functions to convert between time_t and struct xtime (either way) (possibly with information loss, which should be quantifiable).
* TIMEOPT_UTC the epoch is 1970-01-01 00:00:00 UTC and time->sec * does not count inserted leap seconds and did count * removed leap seconds as if they hadn't been removed. * During a leap second (if the implementation is aware * of it), time->sec shows the value for the previous * second and time->nsec continues to increase in the * range 1e9 .. 2e9-1.
// generate a timezone_t description from a string (e.g., POSIX.1 TZ format // or Olsen database entry, or ...). Return *zone = NULL if there is // some syntax error in the string.
void prepare_timezone(timezone_t **zone, char *zonespec);
(Of course, that should be const char *zonespec, with maybe some restricts.) NULL could also occur on other errors - I would suggest having a function to give an error string (so that e.g. problems with timezone files can readily be diagnosed) which would probably entail a change in the interface so that information about the particular error could be saved (remember re-entrancy). For this to be useful it will probably be necessary to copy the POSIX.1 TZ specification into C9X - but it shouldn't be needed to specify what environment variables are used.
// free the time zone descriptor zone and set *zone == TZ_UTC to remove // dangling pointers
I would say setting to TZ_UTC is a quality-of-implementation issue and the standard should simply make *zone undefined after it is freed. In addition state that copies of the timezone_t cannot be used after it is freed. (This assumes copying timezone_t is allowed; if it is, do we require it to be a structure type or simply an object type other than an array type?).
void free_timezone(timezone_t **zone);
#define TZ_DEFAULT (timezone_t *) -2 // eg. from environment var TZ, etc.
There should be two distinct concepts: user's timezone, possibly depending on the environment, and the system's best idea of the local timezone that is guaranteed not to depend on the environment.
struct xtm {
It would be a good idea to use a common prefix for the structure elements (xtm_nsec, xtm_sec, etc.).
long nsec; // nanoseconds after the second [0, 999_999_999] int sec; // seconds after the minute [0, 60]
Where the nanoseconds value in a struct xtime is >= 10^9, the conversion should be defined as long as the seconds point to the end of a minute in the timezone used for conversion. However, POSIX.1 timezones allow offsets that are not whole minutes: in such cases it is probably best to make the conversion in the vicinity of a leapsecond implementation defined (but still require the nsec value in the result to be <10^9?).
int min; // minutes after the hour [0, 59] int hour; // hours since midnight [0, 23] int mday; // day of the month [1, 31] int mon; // months since December [Jan=1, Dec=12] int year; // number of the year int wday; // days since Sunday [Mon=1, Sun=7] int week; // calendar week number (ISO 8601) [1, 53] int wyear; // year of the current week (ISO 8601) int yday; // days since December 31 [1, 366] int offset; // minutes east off UTC
Seconds might be better.
int repeat; // flag indicating first hour after DST
Repetitions can also occur when standard time changes - perhaps this should indicate which (0, 1, 2, ...) of the successive occurances of that time as local time in the given timezone is meant? However, if we are concerned about this, an interface would be needed to tell whether a given time is ambiguous and find all the times it could mean.
timezone_t *zone; // time zone descriptor };
// construct a xtime value from a broken down date and time (return -1 // on error, 0 else)
int mkxtime(const struct xtm *src, struct xtime *dest);
// construct a brocken down date/time representation from an xtm value // (return -1 on error, 0 else)
int mkxtm(const struct xtime *src, const timezone_t *zone, struct xtm *dest);
/* * In time zones with summer time switches, the first hour of winter time * repeats the time values of the previous hour. To distinguish these values * the flag repeat is set to one. (May be, we can also keep the old DST * flag here instead) * * In the tmx given to mkxtime, only the components nsec, sec, min, * hour, mday, mon, year, offset, repeat, and zone are examined. The * values of the other components are irrelevant. Values that are out * of range in nsec, sec, min, hour, mday, mon, year are adjusted * accordingly, for instance if sec is negative, then 60 is added to * sec while 1 is subtracted from min until the value is in the * correct interval before conversion takes place. If zone == * TZ_UNDEFINED, then mkxtime behaves exactly as if TZ_UTC. */
What is appropriate in canonicalisation if the seconds value is 60? The natural expectation is that this causes the minutes to increase unless we are at a leapsecond - but this requires a leapseconds table. The alternative, ending up with nanoseconds of 10^9 in the struct xtime, seems unfortunate. Missing from the specification is some way to tell the precision of the system clock (i.e. some analogue of clock_getres from POSIX). Also, some analogue of difftime to find the difference between two (UTC) times, which should fail if up-to-date leapsecond information is not available for the relevant period. It's not clear if this should be part of the standard, but Clive Feather's issues include conversion between UTC and TAI so I suppose some applications need a leapsecond table to be present. -- Joseph S. Myers jsm28@cam.ac.uk
"Joseph S. Myers" wrote on 1998-09-04 20:38 UTC:
It would be a good idea to use a common prefix for the structure elements (xtm_nsec, xtm_sec, etc.).
I never understood what these common prefixes are good for. What is the reason for calling struct elements tm_sec, tm_min, etc. instead of sec, min, etc.? I find them rather strange and ugly.
int offset; // minutes east off UTC
Seconds might be better.
I think it was a error to allow seconds in the TZ offset in POSIX.1, and I would like to avoid copying such intellectual accidents of the POSIX authors into this proposal. If a local time zone really were defined to have a fixed offset relative to UTC that is not an integral multiple of minutes, then bizarre things would happen near UTC leap seconds. If some politician really should decide that his local time is say 5h 7m 42s behind UTC, then we can't handle this appropriately anyway, and then specifying -04:08 is as acceptable in this silly situation as would be anything else. You would never use such an esoteric time zone for precision applications anyway! Historic time zones with a non-minute offset relative to GMT (UT0, UT1, UT2, etc.) are not defined relative to UTC, and therefore we shouldn't IMHO create the false impression that we could support these with second precision. I prefer sound and consistent semantics here, and I think they are only possible with minute UTC offsets. If you think that civil time zones defined relative to UT1 will become fashionable one day, then why on the other side should we allow only second resolution and not add nanoseconds in addition? I feel the KISS principle dictates minute offsets here.
What is appropriate in canonicalisation if the seconds value is 60? The natural expectation is that this causes the minutes to increase unless we are at a leapsecond - but this requires a leapseconds table. The alternative, ending up with nanoseconds of 10^9 in the struct xtime, seems unfortunate.
I have been thinking about this, and the only reasonable solution I can think of is that we always assume that we do not fall into a leap second. After all, this is only wrong with a probability of less than 1 in 40 million. I cannot think of an application where this would matter. Note that MANY of the previously necessary applications of mktime vanish by the simple fact that we now introduce a well-defined encoding for TIMEOPT_UTC. You do not have to abuse mktime any more to add an hour in a portable way to a time_t. If you care mainly about time intervals and not about UTC, then you should use TIMEOPT_MONOTONIC, which gives you a leapsecond free time scale (which on implementations with a battery clock like every PC has one can even survive across powerdowns). An equivalent of difftime is not necessary in this API for the very same reason. Just don't abuse UTC to calculate time intervals. Thanks a lot, also for your very good other comments. I'll try to consider them in the next draft. 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/>
Date: Sat, 05 Sep 1998 21:40:27 +0100 From: Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> I prefer sound and consistent semantics here, and I think they are only possible with minute UTC offsets. The implementation that I'm typing this message on (Solaris 2.6) has time zones that are not at integral offsets from UTC (e.g. Liberia until 1972). This implementation does not have any semantic problems with leap seconds that are not the last second in a localtime minute, since it does not support leap seconds. I don't think that the C standard should disallow this type of implementation, which is fairly common in practice. If you think that civil time zones defined relative to UT1 will become fashionable one day, then why on the other side should we allow only second resolution and not add nanoseconds in addition? Historical practice was to specify UTC offsets only to the nearest second. For example, I believe that the legal definition of Paris Mean Time (used as the basis for official time in France until 1978) was 9 minutes and 21 seconds ahead of Greenwich Mean Time. I've never seen any records of more-precise UTC offset specifications; I don't think the standard needs to support this. I feel the KISS principle dictates minute offsets here. Isn't it simpler to follow widespread existing practice (POSIX.1, Linux, Solaris, SVR4, BSD, etc., etc.), which uses second offsets? I have been thinking about this, and the only reasonable solution I can think of is that we always assume that we do not fall into a leap second. I don't see why this is the only reasonable solution; it's akin to assuming that we do not fall into the 31st day of a month, since not all months have 31 days. GNU mktime does not make this assumption; if you add 1 to 23:59:59, you'll get 23:59:60 if that leap second happens to exist and if the host support leap seconds. So there's an existence proof that leap seconds can be handled properly. I don't think the C standard needs to _require_ proper handling of leap seconds; but the standard should not _disallow_ it.
It would be a good idea to use a common prefix for the structure elemen= ts (xtm_nsec, xtm_sec, etc.).
I never understood what these common prefixes are good for. I believe that they were put in for historical reasons. In very old versions of the C compiler, all structure members lived in the same name space. Nowadays this original motivation is not important, but the tradition lives on in some places. Personally, I don't think the xtm_ is needed, but I don't care too much one way or the other.
On Sat, 5 Sep 1998, Paul Eggert wrote:
It would be a good idea to use a common prefix for the structure elemen= ts (xtm_nsec, xtm_sec, etc.).
I never understood what these common prefixes are good for.
I believe that they were put in for historical reasons. In very old versions of the C compiler, all structure members lived in the same name space. Nowadays this original motivation is not important, but the tradition lives on in some places. Personally, I don't think the xtm_ is needed, but I don't care too much one way or the other.
There's still the interaction with the macro namespace (user macros named sec, etc.) - with a common prefix the standard could follow POSIX.1 and say that any name beginning xtm_ must not be declared or #defined by the application if <xtime.h> is included - which could help extensibility. (There's a discussion of structure extensibility and user macros in the POSIX.1 rationale - see B.2.7.2.) -- Joseph S. Myers jsm28@cam.ac.uk
<<On Sat, 5 Sep 1998 14:16:54 -0700 (PDT), Paul Eggert <eggert@twinsun.com> said: [quoting others]
It would be a good idea to use a common prefix for the structure elemen= ts (xtm_nsec, xtm_sec, etc.).
I never understood what these common prefixes are good for.
I believe that they were put in for historical reasons. In very old versions of the C compiler, all structure members lived in the same name space.
They still survive for a very good non-historical reason: in all versions of the C preprocessor, all macros live in the same name space. Using unique prefixes such as these makes it possible for the vendor to change the underlying representation and patch things up using preprocessor macros. (Putting on my vendor hat here, just to give one example: when some loser in P1003 decided to rename the `struct timespec' fields to use a `tv_' prefix instead of `ts_', it was trivial to create macro glue which would accept both draft and standard forms. In a hypothetical non-prefixing world, if said loser had decided to rename `nsec' to `nanosec', we would have been totally out of luck.) -GAWollman -- Garrett A. Wollman | O Siem / We are all family / O Siem / We're all the same wollman@lcs.mit.edu | O Siem / The fires of freedom Opinions not those of| Dance in the burning flame MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick
I should make clear that the design of libtai is focused on the needs of real programs. Here are the top two uses of timestamps in existing code: * Subtraction. ``Tell me exactly how much time this took.'' * Conversion to civil time. ``The user wants to know when that was.'' Complete support for both of these functions is IMPOSSIBLE if you don't have an up-to-date leap-second table. (Proof: If you _do_ have both of those functions, you can easily print an up-to-date leap-second table.) Markus Kuhn writes:
My API does not require any leapsecond history to be stored
Then your API is fundamentally broken. How do you expect people to compute accurate time differences?
something which I would never expect to be updated reliably in practice.
In theory the necessary information is already transferred by NTP--- although a new protocol would be a good idea for obvious reasons. ---Dan Binary qmail distributions are allowed! http://pobox.com/~djb/qmail/dist.html
Markus Kuhn wrote on 1998-09-04 19:28 UTC:
// display a brocken down time
size_t strfxtime(char * restrict s, size_t maxsize, const char * restrict format, const struct xtm * restrict timeptr);
Actually, while thinking about it, I believe it might be both more efficient and more flexible to pass to strfxtime the original xtime_t value plus the timezone descriptor, and not the broken-down struct xtm: size_t strfxtime(char * restrict s, size_t maxsize, const char * restrict format, const struct xtime * restrict timeptr, const timezone_t * restrict tzptr); 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/>
participants (5)
-
D. J. Bernstein -
Garrett Wollman -
Joseph S. Myers -
Markus Kuhn -
Paul Eggert