[date_time] timezone bug for boost::posix_time::microsec_clock::local_time()
Hi, I have noticed that there seems to be a problem with the boost date_time library 1.33 (Downloaded about 2 days ago) when trying to use the localtime information under a NetBSD system. Specifically when I have a small test program: #include "boost/date_time/posix_time/posix_time.hpp" #include "boost/date_time/c_local_time_adjustor.hpp" #include <iostream> int main() { using namespace boost::posix_time; ptime loc = microsec_clock::local_time(); ptime utc = microsec_clock::universal_time(); std::cout << "Local: " << to_simple_string(loc) << std::endl; std::cout << "UTC: " << to_simple_string(utc) << std::endl; std::cout << "Local again: " << to_simple_string( boost::date_time::c_local_adjustor<ptime>::utc_to_local(utc)) << std::endl; return 0; } It will display the same time for both UTC time and Local time (Living in Melbourn Australia) where I expected them to differ. I found that the above program would fail unless I did the following: #include "boost/date_time/posix_time/posix_time.hpp" #include "boost/date_time/c_local_time_adjustor.hpp" #include <iostream> int main() { using namespace boost::posix_time; tzset(); ptime loc = microsec_clock::local_time(); ptime utc = microsec_clock::universal_time(); std::cout << "Local: " << to_simple_string(loc) << std::endl; std::cout << "UTC: " << to_simple_string(utc) << std::endl; std::cout << "Local again: " << to_simple_string( boost::date_time::c_local_adjustor<ptime>::utc_to_local(utc)) << std::endl; return 0; } Thanks, Brendon Costa.
On Wed, 17 Aug 2005 12:56:16 +1000, Brendon Costa wrote
Hi,
I have noticed that there seems to be a problem with the boost date_time library 1.33 (Downloaded about 2 days ago) when trying to use the localtime information under a NetBSD system. Specifically when I have a small test program:
#include "boost/date_time/posix_time/posix_time.hpp" #include "boost/date_time/c_local_time_adjustor.hpp"
#include <iostream>
int main() { using namespace boost::posix_time;
ptime loc = microsec_clock::local_time(); ptime utc = microsec_clock::universal_time(); std::cout << "Local: " << to_simple_string(loc) << std::endl; std::cout << "UTC: " << to_simple_string(utc) << std::endl;
std::cout << "Local again: " << to_simple_string( boost::date_time::c_local_adjustor<ptime>::utc_to_local(utc) ) << std::endl; return 0; }
It will display the same time for both UTC time and Local time (Living in Melbourn Australia) where I expected them to differ.
Hi Brendan - All of the 'clock' calls depend on the operating system time zone setup to perform the utc/local conversion. So I suspect something about your system setup is requiring you to call tzset() to initialize the environment for localtime() and gmtime() to work correctly. Not sure why that would be. I presume after tmset() is called once it never needs to be called again? BTW, in 1.33 there's better support for local time than the old c_local_adjustor. You might have a look at the tz database functions that allow you to do adjusment via regions: tz_database tz_db; //data file in lib/date_time/data tz_db.load_from_file("date_time_zonespec.csv"); time_zone_ptr mb_tz = tz_db.time_zone_from_region("Australia/Melbourne"); The returned timezone has string names for the timezone, utc offsets, and daylight savings rules built in. Jeff
Thanks for the reply. See below for notes...
Hi Brendan -
All of the 'clock' calls depend on the operating system time zone setup to perform the utc/local conversion. So I suspect something about your system setup is requiring you to call tzset() to initialize the environment for localtime() and gmtime() to work correctly. Not sure why that would be. I presume after tmset() is called once it never needs to be called again?
Yes it only needs to be called once per process. tzset() will initialize the systems time zone information for use in calls to localtime_r. It needs to be called once for the process before making a call to localtime or a few other functions that implicitly depend upon the timezone information. Here is an excerpt from the localtime man page that is relevant: The gmtime_r() and localtime_r() functions provide the same functionality as gmtime() and localtime() differing in that the caller must supply a buffer area result in which the result is stored; also, localtime_r() does not imply initialization of the local time conversion information; the application may need to do so by calling tzset(3). I am not sure if calling tzset() is a patch that should be made to the boost date time library (Don't know what effects it may have on other systems) or if it is something that I should request for the NetBSD maintainers (I assume there is a good reason localtime_r() does not call tzset() itself, as it is explicitly stated in the NetBSD man pages that the user may need to do so).
BTW, in 1.33 there's better support for local time than the old c_local_adjustor. You might have a look at the tz database functions that allow you to do adjusment via regions:
tz_database tz_db; //data file in lib/date_time/data tz_db.load_from_file("date_time_zonespec.csv"); time_zone_ptr mb_tz = tz_db.time_zone_from_region("Australia/Melbourne");
The returned timezone has string names for the timezone, utc offsets, and daylight savings rules built in.
Is there any way of loading the systems current timezone from the database? I dont want to have to require the user to specify the timezone for each application as a part of its configuration, and it can't be hardcoded as the application can be run in various different timezones. I had a brief look through the new timezone stuff and couldnt find anything for doing this (Though sometimes I am quite blind to what is right in front of me...) Thanks again for the reply. By the way the date time library is very useful! Thanks for all the hard work that has been put into it. Brendon.
On Mon, 22 Aug 2005 11:46:34 +1000, Brendon Costa wrote
Thanks for the reply. See below for notes...
.. snip details...
Here is an excerpt from the localtime man page that is relevant:
...snip details
stored; also, localtime_r() does not imply initialization of the local time conversion information; the application may need to do so by calling tzset(3).
This seems to be a BSD unique rule -- my Linux manpage says the opposite :-(
I am not sure if calling tzset() is a patch that should be made to the boost date time library (Don't know what effects it may have on other systems) or if it is something that I should request for the NetBSD maintainers (I assume there is a good reason localtime_r() does not call tzset() itself, as it is explicitly stated in the NetBSD man pages that the user may need to do so).
Well, there may be some reason, but I'd quibble with it being 'good'. Somehow Linux managed to maintain the same behavior as localtime. So it seems like it is doable. I see 3 options going forward (or while we wait for BSD to change this): 1) restore the 1.32 behavior by disabling _r functions 2) make the user call tzset once before calling date-time clock functions 3) have date-time call tzset once for BSD only You can do 1 and 2 yourself -- 3 can't happen till the next release...
BTW, in 1.33 there's better support for local time than the old c_local_adjustor.
Is there any way of loading the systems current timezone from the database? I dont want to have to require the user to specify the timezone for each application as a part of its configuration, and it can't be hardcoded as the application can be run in various different timezones. I had a brief look through the new timezone stuff and couldnt find anything for doing this (Though sometimes I am quite blind to what is right in front of me...)
No, unfortunately there isn't that I know (if someone knows a solution, I'd love to hear it). The main problem is that system API's seem like they have about half the information to really specify a timezone. However, you do have some options. If you can force the installation of a timezone environment string holding a posix time zone specification then you can read it and construct a posix_time_zone. On some systems that might actually work out of the box. Or you could install a config file with the posix string in it.
Thanks again for the reply. By the way the date time library is very useful! Thanks for all the hard work that has been put into it.
You're welcome :-) Jeff
participants (2)
-
Brendon Costa
-
Jeff Garland