FW: C/C++ library that parses TZ data?
I'm forwarding this message from Dario Teixeira, who is not on the time zone mailing list. Those of you who are on the list, please direct replies appropriately. --ado -----Original Message----- From: Dario Teixeira [mailto:darioteixeira@yahoo.com] Sent: Wednesday, February 09, 2011 11:03 To: tz@lecserver.nci.nih.gov Subject: C/C++ library that parses TZ data? Hi, I have a problem which is fairly common when one is running a web application that wishes to display timestamps localised towards each user's time zone. Basically, I need a function that takes as input a timestamp in UTC and a time zone specified in the Zoneinfo convention (ex: "Europe/Lisbon"), and returns the localised version of that timestamp, including a time zone abbreviation aware of daylight savings. Example: 2010-01-01 15:30, "Europe/Lisbon" -> 2010-01-01 15:30 WET 2010-01-01 15:30, "Europe/Paris" -> 2010-01-01 16:30 CET 2010-07-01 15:30, "Europe/Lisbon" -> 2010-07-01 16:30 WEST 2010-07-01 15:30, "Europe/Paris" -> 2010-07-01 17:30 CEST Since the zoneinfo data is present in every Unix system and glibc includes routines for parsing it, interfacing with glibc seemed the obvious solution. Unfortunately, glibc was not designed with this use case in mind. In fact, the glibc interface to zoneinfo can be described as "sui generis" if one is feeling charitable, or "insane" if truth must be told. Specifically, to obtain the localised version of a given timestamp, one must first set the 'TZ' environment variable with the target timezone, and then invoke 'localtime'. The abbreviated name of the timezone can be found in the global 'tzname' array: at position 'tzname[0]' if daylight savings are not in effect and at position 'tzname[1]' if they are. A quick search through glibc's bugzilla shows I'm not the only one to find this interface anachronistic [1], but it also reveals that it is unlikely to change. So, my question is if someone is aware of some alternative library in C or C++ that provides this same functionality, but is friendlier towards concurrent applications. Best regards, Dario Teixeira [1] http://sources.redhat.com/bugzilla/show_bug.cgi?id=11620
On Wed, 9 Feb 2011, Olson, Arthur David (NIH/NCI) [E] wrote:
I have a problem which is fairly common when one is running a web application that wishes to display timestamps localised towards each user's time zone. Basically, I need a function that takes as input a timestamp in UTC and a time zone specified in the Zoneinfo convention (ex: "Europe/Lisbon"), and returns the localised version of that timestamp, including a time zone abbreviation aware of daylight savings. Example:
2010-01-01 15:30, "Europe/Lisbon" -> 2010-01-01 15:30 WET 2010-01-01 15:30, "Europe/Paris" -> 2010-01-01 16:30 CET
2010-07-01 15:30, "Europe/Lisbon" -> 2010-07-01 16:30 WEST 2010-07-01 15:30, "Europe/Paris" -> 2010-07-01 17:30 CEST
Since the zoneinfo data is present in every Unix system and glibc includes routines for parsing it, interfacing with glibc seemed the obvious solution. Unfortunately, glibc was not designed with this use case in mind. In fact, the glibc interface to zoneinfo can be described as "sui generis" if one is feeling charitable, or "insane" if truth must be told. Specifically, to obtain the localised version of a given timestamp, one must first set the 'TZ' environment variable with the target timezone, and then invoke 'localtime'. The abbreviated name of the timezone can be found in the global 'tzname' array: at position 'tzname[0]' if daylight savings are not in effect and at position 'tzname[1]' if they are. A quick search through glibc's bugzilla shows I'm not the only one to find this interface anachronistic [1], but it also reveals that it is unlikely to change.
So, my question is if someone is aware of some alternative library in C or C++ that provides this same functionality, but is friendlier towards concurrent applications.
I've written "timelib"; which is also part of the core of PHP's date/time functionality. It's not the most brilliant piece of code, but it does do the trick: http://svn.xdebug.org/cgi-bin/viewvc.cgi/timelib/trunk/?root=php (svn co http://svn.xdebug.org/svn/php/timelib/trunk timelib) cheers, Derick -- http://derickrethans.nl | http://xdebug.org Like Xdebug? Consider a donation: http://xdebug.org/donate.php twitter: @derickr and @xdebug
Hi,
I've written "timelib"; which is also part of the core of PHP's date/time functionality. It's not the most brilliant piece of code, but it does do the trick: http://svn.xdebug.org/cgi-bin/viewvc.cgi/timelib/trunk/?root=php (svn co http://svn.xdebug.org/svn/php/timelib/trunk timelib)
Thanks for the reply. How insulated are the zoneinfo parsing routines from all the PHP-related stuff? Mind you that I really just need the functionality that I described. Best regards, Dario Teixeira
On Wed, 9 Feb 2011, Dario Teixeira wrote:
I've written "timelib"; which is also part of the core of PHP's date/time functionality. It's not the most brilliant piece of code, but it does do the trick: http://svn.xdebug.org/cgi-bin/viewvc.cgi/timelib/trunk/?root=php (svn co http://svn.xdebug.org/svn/php/timelib/trunk timelib)
Thanks for the reply. How insulated are the zoneinfo parsing routines from all the PHP-related stuff? Mind you that I really just need the functionality that I described.
It does not depend on anything. It's stand alone. PHP depends on (a fork) of this library. cheers, Derick -- http://derickrethans.nl | http://xdebug.org Like Xdebug? Consider a donation: http://xdebug.org/donate.php twitter: @derickr and @xdebug
Hello, We utilize the C# library, http://zoneinfo.codeplex.com/Thread/View.aspx?ThreadId=50756 This Loads the library into the application's cache as a global static variable and gives you direct access to zone conversions using the utc time and a zone name. There are other solutions similar to this avaialble; but, I'm not sure from a C or C++ perspective. Hope this helps -Isaac Iformata Communications LLC 130 West Second St, Suite 1111, Dayton, Ohio 45402 Main: +1-937-832-6900 Direct: +1-937-832-6961 Please consider the environment before printing. This communication (including any attachments) may contain privileged or confidential information of Iformata LLC and is intended for a specific individual. If you are not the intended recipient, you should delete this communication, including any attachments without reading or saving them in any manner, and you are hereby notified that any disclosure, copying, or distribution of this communication, or the taking of any action based on it, is strictly prohibited; if you received this in error please notify me immediately by replying to this message stating you received it in error. On Feb 9, 2011, at 11:23 AM, Olson, Arthur David (NIH/NCI) [E] wrote: I'm forwarding this message from Dario Teixeira, who is not on the time zone mailing list. Those of you who are on the list, please direct replies appropriately. --ado -----Original Message----- From: Dario Teixeira [mailto:darioteixeira@yahoo.com] Sent: Wednesday, February 09, 2011 11:03 To: tz@lecserver.nci.nih.gov<mailto:tz@lecserver.nci.nih.gov> Subject: C/C++ library that parses TZ data? Hi, I have a problem which is fairly common when one is running a web application that wishes to display timestamps localised towards each user's time zone. Basically, I need a function that takes as input a timestamp in UTC and a time zone specified in the Zoneinfo convention (ex: "Europe/Lisbon"), and returns the localised version of that timestamp, including a time zone abbreviation aware of daylight savings. Example: 2010-01-01 15:30, "Europe/Lisbon" -> 2010-01-01 15:30 WET 2010-01-01 15:30, "Europe/Paris" -> 2010-01-01 16:30 CET 2010-07-01 15:30, "Europe/Lisbon" -> 2010-07-01 16:30 WEST 2010-07-01 15:30, "Europe/Paris" -> 2010-07-01 17:30 CEST Since the zoneinfo data is present in every Unix system and glibc includes routines for parsing it, interfacing with glibc seemed the obvious solution. Unfortunately, glibc was not designed with this use case in mind. In fact, the glibc interface to zoneinfo can be described as "sui generis" if one is feeling charitable, or "insane" if truth must be told. Specifically, to obtain the localised version of a given timestamp, one must first set the 'TZ' environment variable with the target timezone, and then invoke 'localtime'. The abbreviated name of the timezone can be found in the global 'tzname' array: at position 'tzname[0]' if daylight savings are not in effect and at position 'tzname[1]' if they are. A quick search through glibc's bugzilla shows I'm not the only one to find this interface anachronistic [1], but it also reveals that it is unlikely to change. So, my question is if someone is aware of some alternative library in C or C++ that provides this same functionality, but is friendlier towards concurrent applications. Best regards, Dario Teixeira [1] http://sources.redhat.com/bugzilla/show_bug.cgi?id=11620
Dario, I think ICU4C [http://icu-project.org/] provides features which you need. I'd recommend you to check following ICU user guide sections - http://userguide.icu-project.org/formatparse/datetime http://userguide.icu-project.org/datetime/timezone -Yoshito
-----Original Message----- From: Dario Teixeira [mailto:darioteixeira@yahoo.com] Sent: Wednesday, February 09, 2011 11:03 To: tz@lecserver.nci.nih.gov Subject: C/C++ library that parses TZ data?
Hi,
I have a problem which is fairly common when one is running a web application that wishes to display timestamps localised towards each user's time zone. Basically, I need a function that takes as input a timestamp in UTC and a time zone specified in the Zoneinfo convention (ex: "Europe/Lisbon"), and returns the localised version of that timestamp, including a time zone abbreviation aware of daylight savings. Example:
2010-01-01 15:30, "Europe/Lisbon" -> 2010-01-01 15:30 WET 2010-01-01 15:30, "Europe/Paris" -> 2010-01-01 16:30 CET
2010-07-01 15:30, "Europe/Lisbon" -> 2010-07-01 16:30 WEST 2010-07-01 15:30, "Europe/Paris" -> 2010-07-01 17:30 CEST
Since the zoneinfo data is present in every Unix system and glibc includes routines for parsing it, interfacing with glibc seemed the obvious solution. Unfortunately, glibc was not designed with this use case in mind. In fact, the glibc interface to zoneinfo can be described as "sui generis" if one is feeling charitable, or "insane" if truth must be told. Specifically, to obtain the localised version of a given timestamp, one must first set the 'TZ' environment variable with the target timezone, and then invoke 'localtime'. The abbreviated name of the timezone can be found in the global 'tzname' array: at position 'tzname[0]' if daylight savings are not in effect and at position 'tzname[1]' if they are. A quick search through glibc's bugzilla shows I'm not the only one to find this interface anachronistic [1], but it also reveals that it is unlikely to change.
So, my question is if someone is aware of some alternative library in C or C++ that provides this same functionality, but is friendlier towards concurrent applications.
Best regards, Dario Teixeira
[1] http://sources.redhat.com/bugzilla/show_bug.cgi?id=11620
On Feb 9, 2011, at 8:23 AM, Olson, Arthur David (NIH/NCI) [E] wrote:
Since the zoneinfo data is present in every Unix system
(Well, actually, I'm not sure HP-UX has it; they had their own scheme for handling other time zones. Perhaps they've switched to zoneinfo recently. Some older UN*Xes didn't use zoneinfo, e.g. pre-SVR4 System V from AT&T.)
and glibc includes routines for parsing it, interfacing with glibc seemed the obvious solution. Unfortunately, glibc was not designed with this use case in mind.
For better or worse, the use case for which glibc's interface was designed was the "compatibility with the API that's been in UNIX since time immemorial" use case. The UNIX APIs - localtime() and mktime() - are pretty good for the "what time is it in my time zone?" use case (although it, alas, took entirely too long for mktime() to become part of that API; the tz code might have pushed it in that direction). For the "what time is it in an arbitrary time zone" use case, not so much; back in the 1970's, when the UNIX API was first created, that was perhaps a less common case. As the person who submitted the bug you cite said, "This is design of the pre-internet era." - and, in fact, localtime() and company were designed not just in the pre-Internet era, but in the pre-TCP/IP era (RFCs 791 and 793 have dates in September 1981). Has any consensus been reached on the proposal in the "Extension to tzcode to support additional timezones" thread? If we provide APIs to handle time conversions for multiple time zones in the same process in our sample code, that might encourage those OSes whose time conversion routines are based on our sample code to pick up our implementations and possibly encourage those OSes whose time conversion routines aren't based on our sample code (e.g., anybody who uses glibc) to pick up the APIs. There were some open issues that don't seem to have been completely resolved.
In fact, the glibc interface to zoneinfo can be described as "sui generis" if one is feeling charitable,
Well, given that OSes with the same interface include, err, umm, Solaris, HP-UX, AIX, *BSD, Tru64 UNIX, and Mac OS X, in addition to most Linux distributions (and a bunch of older UNIXes no longer with us or no longer being further developed), and all of them, with the exception of the Linux distributions, not using glibc, I don't think "sui generis" is accurate - the glibc APIs are not unique to glibc, they're just doing what every other UN*X is doing.
or "insane" if truth must be told.
I think "not at all useful for an operation that many applications require" would be more accurate; it works well for the use case for which it was intended, but it's a bit craptastic for anybody who cares about other time zones, and there are a number of developers like that out there.
The abbreviated name of the timezone can be found in the global 'tzname' array: at position 'tzname[0]' if daylight savings are not in effect and at position 'tzname[1]' if they are.
Well, that particular AT&T invention was a bit suboptimal - it's hostile even to applications that only care about one time zone but that are converting times in more than one thread, but, well, it was concocted before multi-threading support was very common in UN*X, so it was more of a case of not being very future-proof than being completely crazy. But, in any case, yes, an API that better handles that case would be nice.
Hi,
(Well, actually, I'm not sure HP-UX has it; they had their own scheme for handling other time zones. Perhaps they've switched to zoneinfo recently. Some older UN*Xes didn't use zoneinfo, e.g. pre-SVR4 System V from AT&T.)
I meant "Unix" as in "most popular Desktop Unixen"...
For better or worse, the use case for which glibc's interface was designed was the "compatibility with the API that's been in UNIX since time immemorial" use case. The UNIX APIs - localtime() and mktime() - are pretty good for the "what time is it in my time zone?" use case (although it, alas, took entirely too long for mktime() to become part of that API; the tz code might have pushed it in that direction). For the "what time is it in an arbitrary time zone" use case, not so much; back in the 1970's, when the UNIX API was first created, that was perhaps a less common case. As the person who submitted the bug you cite said, "This is design of the pre-internet era." - and, in fact, localtime() and company were designed not just in the pre-Internet era, but in the pre-TCP/IP era (RFCs 791 and 793 have dates in September 1981).
Yes, I realise there's a huge historical baggage associated with the current API, not to mention a POSIX mandate.
Has any consensus been reached on the proposal in the "Extension to tzcode to support additional timezones" thread? If we provide APIs to handle time conversions for multiple time zones in the same process in our sample code, that might encourage those OSes whose time conversion routines are based on our sample code to pick up our implementations and possibly encourage those OSes whose time conversion routines aren't based on our sample code (e.g., anybody who uses glibc) to pick up the APIs. There were some open issues that don't seem to have been completely resolved.
Indeed, I've noted that glibc and other projects use essentially your code for tzcode handling, so if you were to make those API additions, there's a better chance it would be also picked up downstream. Nevertheless, the attitude expressed by the glibc maintainer in the bug report I mentioned does not bode well for frictionless communication [1]...
Well, given that OSes with the same interface include, err, umm, Solaris, HP-UX, AIX, *BSD, Tru64 UNIX, and Mac OS X, in addition to most Linux distributions (and a bunch of older UNIXes no longer with us or no longer being further developed), and all of them, with the exception of the Linux distributions, not using glibc, I don't think "sui generis" is accurate - the glibc APIs are not unique to glibc, they're just doing what every other UN*X is doing.
I singled out glibc when perhaps blaming POSIX might have been more correct.
I think "not at all useful for an operation that many applications require" would be more accurate; it works well for the use case for which it was intended, but it's a bit craptastic for anybody who cares about other time zones, and there are a number of developers like that out there.
Though slightly hyperbolic as my rethoric may have been, the truth is that this is 2011, and there have been for many years now tangible drawbacks to the antiquated API in glibc and its counterparts. Most notably is that anyone who needs a functional interface to the tzcode routines (ie, one which does not require mutating global state) needs to copy & paste & adapt the code. This sort of code replication is inefficient and potentially dangerous if a security vulnerability is found (instead of trusting a single update from glibc you have to hope all the projects using the code will fix the same flaw). As for what that API should look like, there are essentially three requirements: 1) Keep the existing API for backwards compatibility. 2) A hypothetical 'timezonetime' function which takes as parameter a timestamp and a timezone should be truly functional in the sense of not having side-effects nor requiring pre-setting some global environment variable. 3) The API should cater for optimised conversion. This means that the caller should have the option of keeping a cache of parsed zoneinfo files, and the invocation of 'timezoneinfo' can be given one of these. For example: (in pseudo-code) zninfo = parsezoneinfo ('Europe/Lisbon'); time_str = timezonetime (zninfo, current_time); Thanks again for your attention! Best regards, Dario [1] http://sources.redhat.com/bugzilla/show_bug.cgi?id=11620
participants (6)
-
Dario Teixeira -
Derick Rethans -
Guy Harris -
Isaac Hogue -
Olson, Arthur David (NIH/NCI) [E] -
yoshito_umaoka@us.ibm.com