Re-entrant, any-zone mktime()-equivalent?
Has anyone ever developed patches for tzcode to support a function that is the equivalent of timelocal()/mktime() and timegm() for arbitrary time zones? What I'm looking for is something that would be the rough equivalent of: time_t timetz(struct tm *tm, char *tz) { time_t t; char *oldTZ = getenv("TZ"); setenv("TZ", tz, 1); tzset(); t = mktime(tm); if (oldTZ != NULL) { setenv("TZ", oldTZ, 1); } else { unsetenv("TZ"); } tzset(); return t; } However, I'd like to have a function which a) worked correctly in multi-threaded environments, and b) reported an error message if the timezone string was invalid, rather than just falling back to GMT. I need this for a Internet Telephony server which needs to support time-of-day routing for users in arbitrary timezones, and I want to use the TZ database names to identify these timezones. (This is for an implementation of the Call Processing Language, soon (pending IESG approval) to be an IETF Proposed Standard. <http://www.cs.columbia.edu/~lennox/draft-ietf-iptel-cpl-04.txt>.) Obviously, writing such a function would require some fairly intrusive hacking on tzcode -- especially since tzcode uses static variables rather liberally. Before I start bashing on the code, I'd appreciate any advice anyone else has, especially if the work's already been done. Thanks for any advice or pointers anyone can give! -- Jonathan Lennox lennox@cs.columbia.edu
From: Jonathan Lennox <lennox@cs.columbia.edu> Date: Wed, 15 Nov 2000 17:41:18 -0500 (EST)
Has anyone ever developed patches for tzcode to support a function that is the equivalent of timelocal()/mktime() and timegm() for arbitrary time zones?
Not that I know of. The subject has come up more than once, but nobody has done it as far as I know. There is some Java code to do it: see <http://www.bmsi.com/java/ZoneInfo.java>. You might also consider starting from the GNU C library code base. There is a serious (i.e. it will probably be implemented soon) proposal to do thread-safe locales with glibc in <http://www.cygnus.com/~drepper/tllocale.ps.bz2>. The same basic idea applies to time zones. The glibc maintainer might buy back changes along these lines.
<http://www.cs.columbia.edu/~lennox/draft-ietf-iptel-cpl-04.txt>.)
From the tz list's point of view, Appendix A of that draft is perhaps the most interesting one. But frankly I couldn't follow it -- I have a vague impression of what it's doing, but I couldn't make heads or tails of it really, even though I read the earlier part of the RFC. Some examples would help immensely.
I did notice this point: 1. Compute the time of the call, in the timezone of the time switch. (No step after this needs to consider time zones -- all calculations are done using continuously-running standard Gregorian time.) Suppose the current time zone is America/Los_Angeles, the time of the call is 2000-04-02 01:30 -0800 (PST), and you have a two-hour time slot. (As I don't follow your terminology, I'm using informal terms like "time slot".) Since you use standard Gregorian time, I guess you'll say that 2000-04-02 03:45 -0700 falls within the two-hour time slot. But 03:45 actually is only 1 hour and 15 minutes after the time of the call, due to a DST change. Is that what the user wants? As an extreme case, consider Pacific/Kiritimati. In that time zone there is no day 1995-01-01, as they moved the clock 24 hours ahead at midnight. What will Algorithm A do with that case? There are also cases of clocks moving backwards 24 hours. It might be helpful for you to supply examples that cover cases like these.
On Wednesday, November 15 2000, "Paul Eggert" wrote to "lennox@cs.columbia.edu, tz@elsie.nci.nih.gov" saying:
<http://www.cs.columbia.edu/~lennox/draft-ietf-iptel-cpl-04.txt>.)
From the tz list's point of view, Appendix A of that draft is perhaps the most interesting one. But frankly I couldn't follow it -- I have a vague impression of what it's doing, but I couldn't make heads or tails of it really, even though I read the earlier part of the RFC. Some examples would help immensely.
There's Java code available at <http://www.cs.columbia.edu/~lennox/Cal-Code/>, which implements the algorithm of Appendix A. This may be more comprehensible. The short description of the algorithm is: we have an instant of time and a recurrence rule of time periods, and we want to find out if the former falls within an instance of the latter. To do this, we determine the unique period which a) possibly could be one of the repititions of the rule, and b) possibly could contain the time instant. (By constraining the structure of rules various ways, we guarantee that this period is unique). Then we check whether both points A and B are actually true. I admit this algorithm approaches the problem somewhat "backward" -- it had to, in order to get an O(1) solution to it. (The obvious solution would have been just to enumerate every recurrence of the rule, until we pass the instant.)
I did notice this point:
1. Compute the time of the call, in the timezone of the time switch. (No step after this needs to consider time zones -- all calculations are done using continuously-running standard Gregorian time.)
Suppose the current time zone is America/Los_Angeles, the time of the call is 2000-04-02 01:30 -0800 (PST), and you have a two-hour time slot. (As I don't follow your terminology, I'm using informal terms like "time slot".) Since you use standard Gregorian time, I guess you'll say that 2000-04-02 03:45 -0700 falls within the two-hour time slot. But 03:45 actually is only 1 hour and 15 minutes after the time of the call, due to a DST change. Is that what the user wants?
I think it is, given that the purpose of the CPL is to make decisions about how a user's phone calls are routed. For example, imagine that a user has the rule "I don't want my phone to ring between 10 pm and 7 am." In the language of the CPL (which is derived from iCal's recurrence rules), this is stated either as something like "2000-11-16, 10 pm - 2000-11-17, 7am; repeat daily" or as something like "2000-11-16, 10 pm, for 9 hours; repeat daily". Now, the question is what the user would expect to have happen the morning of April 1, 2001 (assuming your example of America/Los_Angeles) and on subsequent transitition dates. You could argue that the behavior should be different in the two cases, and for the latter representation that the block should actually stop working at 6 am on that day. However, I felt it was much more likely that the semantics of the two cases are actually intended to be the same thing; and having a phone ring at 6:30 am on April 1st, or having it not ring at 7:30 am on October 28, 2001, would violate the principle of least surprise.
As an extreme case, consider Pacific/Kiritimati. In that time zone there is no day 1995-01-01, as they moved the clock 24 hours ahead at midnight. What will Algorithm A do with that case? There are also cases of clocks moving backwards 24 hours.
It should handle it correctly, as far as I know -- it just takes the current instant and derives the current civil time from it, which is always a valid (albeit not one-to-one) operation. The assumption the algorithm makes is that the user's desired treatment of their phone calls is determined by the current civil date and time, not by the passage of time in a monotonically running clock. Thus, if something special happens on Sundays in Kiritimati, it just didn't happen that week. Likewise, American expats in Samoa in 1879 had their celebrations of the Fourth of July twice (not that there were likely too many telephones there at that point). I probably should have included rather more text in the specification explaining these considerations; and I probably should have run it by the TZ list sooner. Unfortunately, given the stage the document is at in the IETF standardization process, it's somewhat late to add it now. -- Jonathan Lennox lennox@cs.columbia.edu
At 17:54 -0500 2000-11-16, Jonathan Lennox wrote:
...stated either as something like "2000-11-16, 10 pm - 2000-11-17, 7am; repeat daily" or as something like "2000-11-16, 10 pm, for 9 hours; repeat daily"...I felt it was much more likely that the semantics of the two cases are actually intended to be the same thing; and having a phone ring at 6:30 am on April 1st, or having it not ring at 7:30 am on October 28, 2001, would violate the principle of least surprise.
Shouldn't that be the other way around? Namely: "...having a phone not ring at 7:30 am on April 1st, or having it ring at 6:30 am on October 28, 2001..." I'm also puzzled by: At 18:35 -0800 2000-11-15, Paul Eggert wrote:
Suppose the current time zone is America/Los_Angeles, the time of the call is 2000-04-02 01:30 -0800 (PST), and you have a two-hour time slot. (As I don't follow your terminology, I'm using informal terms like "time slot".) Since you use standard Gregorian time, I guess you'll say that 2000-04-02 03:45 -0700 falls within the two-hour time slot. But 03:45 actually is only 1 hour and 15 minutes after the time of the call, due to a DST change. Is that what the user wants?
Isn't 03:45 more than 2 hours after 01:30 (all other things being equal) and thus _outside_ the two-hour time slot? The fact that in the example it's only 1 hour 15 minutes later (instead of 2 hours 15 minutes later) because of a time-offset change brings it _within_ the two-hour time slot, doesn't it? Am I just misunderstanding what a time slot is and what's within it and what's not? Sorry if I'm making too much fuss over what are possibly insignificant errors. --Alex _______________ Alex LIVINGSTON Macintosh and Lotus Notes Support / Information Technology (IT) Australian Graduate School of Management (AGSM) UNSW SYDNEY NSW 2052 / Australia Facsimile: +61 2 9931-9349 / Telephone: +61 2 9931-9264 Time : UTC+11---[last Mar. Sun.---UTC+10---[last Aug. Sun.---UTC+11--- At end of today, Friday, November 17, time since epoch (1-1-1 at 00:00:00) = 730441 days = 1999.87953209 average Gregorian years time until 3rd millennium, 21st century, 201st decade, 2001st year = 44 days = .12046791 average Gregorian years
Jonathan Lennox wrote:
Has anyone ever developed patches for tzcode to support a function that is the equivalent of timelocal()/mktime() and timegm() for arbitrary time zones?
We had to do a similar thing for our system for online FX option pricing. We needed different threads in the server to be in different timezones. Our original intention was to port tzcode to NT (yes, our servers run NT, sigh), then add the patch you are thinking of. Unfortunately time constraints prohibited us from doing it the right way, so we just ended up putting some POSIXy wrappers around the ugly Win32 functions. (You can do what you want using the Win32 API, but it's not pretty, and clearly un- portable). So, at least we are no wronger about timezones than the OS. It is possible that we will revisit this project, and reimplement our interfaces using tzcode instead. I will definitely post patches if this happens. joe
participants (4)
-
Alex LIVINGSTON -
Joe Bamberg -
Jonathan Lennox -
Paul Eggert