Writing code that deals with time values
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com This will be my last posting on this topic. -- Here is a short primer for people interested in writing working code: Q: I want to use arbitrary dates on Mac OS X A: Use NSDate/CFDate 32 bit time_t Jan 1 1970 00:00 +/- 2^31 seconds (Y1902 - Y2038) 64 bit time_t Y1970 +/- 2^63 seconds (~ +/- 209 billion years) struct timespec same as time_t struct timeval same as time_t struct tm Y1900 +/- 2^31 years (~ +/- 2 billion years) -- Terry _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... Q: But I want my code to be portable between Linux, Mac OS X, and other UNIX operating systems; what interfaces can I use? A: You can use the POSIX C library functions and you can use the POSIX system functions, as long as you are aware of natural type restrictions and what POSIX does or doesn't guarantee in terms of implementation details Q: What are the natural types used by the POSIX C library functions? A: The POSIX C library functions use a mix of struct tm, struct timespec, struct timeval, and time_t Q: What are the natural types used by the POSIX system functions? A: The POSIX system functions use a mix of struct timespec, struct timeval, and time_t Q: What is the lowest common denominator - the "natural" type - for time values on POSIX systems? A: time_t, which is a signed value in seconds relative to the UNIX Epoch of January 1st 1970 Q: What are the restrictions on date ranges are supported by these types? A: It depends on the type, and whether the system is 32 or 64 bit: Q: Doesn't that mean that there's potentially a problem for UNIX systems around Y2038? A: Yes. Computer scientists are aware of the issue, and have known about it for many years. There is even a Wikipedia article on it. Q: So if I am using POSIX interfaces, I should use a 64 bit time_t or struct tm to represent large date ranges? A: struct tm *can* represent large date ranges, but conversion is ambiguous; use a 64 bit time_t where possible to avoid the ambiguity. Q: What if I don't want to use a 64 bit time_t , can I use a struct tm instead? A: Either limit the ranges in which your software is going to operate, or carry around your own functions; the POSIX C library function conversions are ambiguous; it's impossible to use struct tm and get consistent cross-platform results Q: Why? A: The POSIX interfaces which deal with struct tm, as specified, lack reflexivity under certain conditions. Q: What does that mean? A: There is no function to get the current time without conversion from a time_t, and the range of the conversion into and out of time_t is bounded by the range bounds on time_t, and some of the functions are inconsistent or insufficiently specific. This translates to not being able to trust the conversion routines in a couple of cases. Q: What if I disagree with the Mac OS X interpretation of a standards ambiguity? A: File a bug. Q: What are the ambiguous cases? A: You can't trust the conversion routines to be able to be called to convert, and then convert back a value, and give the original input back to you. This is both because some values you could put in a struct tm can't fit into a time_t (as an internal implementation detail), and because some of the conversion routines don't specify an Epoch date (strftime(3)). Also, because there is no method of obtaining the current time that doesn't transit a system interface, there's no way to get the current time as anything other than a time_t value. Q: So I can't get the current time as a struct tm? A: No. Not without calling one of gmtime(3), gmtime_r(3), localtime(3), or localtime_r(3) on the results of a call to time(2), which only returns a time_t. Q: So my code will always have the Y2038 bug? A: No. You can compile your code as 64 bit, which will give you a 64 bit time_t; this will prevent having the Y2038 bug. Q: How do I avoid POSIX interface ambiguity? A: Start by using 4 byte year+century fields instead of 2 byte year- within-century fields; avoid %y and %C as separate formatting characters. If you insist on using these format specifiers, the best you can achieve is changing your T2038 bug into a Y2069 bug instead, assuming you never care about the current time after Y2038. Q: What's the bottom line, if time_t is 32 bits on my system? A: Your code has the Y2038 bug, if it deals with the current time or does math on time using standard functions, such as difftime(3). Q: Are there any other alternatives? A: Yes. Carry around your own private non-POSIX date manipulation functions as part of your software. This will make your code behave consistently on all platforms. This email sent to site_archiver@lists.apple.com
participants (1)
-
Terry Lambert