Reputation: 14717
Given a specific time zone other than the local timezone (e.g. America/Los_Angeles
), how can I find the current GMT offset of this timezone? The intention is to have this work with respect to DST changes. That is, the GMT offset for Los Angeles is -8, which is adjusted to -7 during daylight savings.
Some other answers suggest manipulating the TZ
environment variable which affects what functions like localtime
return, but I want a solution that does not mess with environment variables (being non-reentrant for instance).
It also appears that all this information is available on /usr/share/zoneinfo
via zdump
, but it's not obvious how I can get to this from within C++.
Upvotes: 1
Views: 3206
Reputation: 219428
New information for an old question:
There is a new open source timezone library which will completely parse your local copy of the IANA database (including all historical data and even leap seconds). A C++11 or C++14 compiler is required. You can use this to find out detailed information about any timezone, at any time. Detailed information about this library is included in the link above.
One example program is:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
auto zone = locate_zone("America/Los_Angeles");
auto tp = system_clock::now();
auto info = zone->get_info(tp);
std::cout << "Information for " << zone->name() << " at " << tp << " UTC is:\n"
<< info << '\n';
tp = sys_days{nov/7/2014} + 53min;
info = zone->get_info(tp);
std::cout << "Information for " << zone->name() << " at " << tp << " UTC is:\n"
<< info << '\n';
}
Which just output for me:
Information for America/Los_Angeles at 2015-07-18 19:34:30.112820 UTC is:
2015-03-08 10:00:00
2015-11-01 09:00:00
-07:00:00
01:00
PDT
Information for America/Los_Angeles at 2014-11-07 00:53:00.000000 UTC is:
2014-11-02 09:00:00
2015-03-08 10:00:00
-08:00:00
00:00
PST
This output is interpreted as follows:
The day I'm answering this question, the UTC offset for "America/Los_Angeles" is -7 hours, and the abbreviation for the timezone is PDT. This is offset 1 hour from the region's "standard time". This offset and abbreviation are valid at least over this range of UTC time points: [2015-03-08 10:00:00, 2015-11-01 09:00:00).
The day this question was asked, the UTC offset for "America/Los_Angeles" was -8 hours, and the abbreviation for the timezone was PST. This was not offset from the region's "standard time". This offset and abbreviation are valid at least over this range of UTC time points: [2014-11-02 09:00:00, 2015-03-08 10:00:00).
This is a github project, and pull requests to help port it to as many C++11/14 platforms as practical are welcome.
Upvotes: 2
Reputation: 241890
One approach you might consider is to use ICU. It contains (among other things) functions to convert between time zones. See the documentation for the TimeZone
class.
For example, you can create a time zone object:
TimeZone *tz = TimeZone::createTimeZone("America/Los_Angeles");
You can then use methods like getOffset
.
See also, the ICU Time Zone User Guide, and this complete example.
Upvotes: 2
Reputation: 14717
I've found a solution using Boost but it seems a bit roundabout. It uses the following steps:
It's probably clearer with a sample program:
#include <iostream>
#include <boost/date_time/local_time/local_time.hpp>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: program tz_name\n";
return 1;
}
// Load time zone database
boost::local_time::tz_database tz_db;
tz_db.load_from_file("date_time_zonespec.csv");
// Current time
auto t = boost::posix_time::second_clock::local_time();
// Get the time for GMT; we'll use this to compare against other time zones
boost::local_time::time_zone_ptr gmt_tzp{new boost::local_time::posix_time_zone("GMT")};
boost::local_time::local_date_time gmt{t, gmt_tzp};
// Get time for specific time zone
boost::local_time::local_date_time local{t, tz_db.time_zone_from_region(argv[1])};
// Calculate difference between local time and GMT time
auto difference = local.local_time() - gmt.local_time();
// Print some information
auto offset_minutes = difference.total_seconds() / 60;
std::cout << "Zone " << local.zone()->std_zone_name() << " GMT offset minutes " << offset_minutes << "\n";
return 0;
}
Sample usage and output:
$ ./a.out "America/Los_Angeles"
Zone Pacific Standard Time GMT offset minutes -480
$ ./a.out "Asia/Dubai"
Zone GST GMT offset minutes 240
$ ./a.out "Australia/Sydney"
Zone EST GMT offset minutes 660
Upvotes: 2