给定本地时区以外的特定时区(例如America/Los_Angeles
),如何找到该时区的当前GMT偏移量?其目的是使此工作与DST变化有关。也就是说,洛杉矶的GMT偏移量为-8,在夏令时调整为-7。
其他一些答案建议操作TZ
环境变量,它会影响localtime
返回的函数,但我想要一个不与环境变量混淆的解决方案(例如,不可重入)。
所有这些信息似乎都可以通过zdump
在/usr/share/zoneinfo
上获得,但我如何从C中获取这些信息并不明显。
您可以考虑的一种方法是使用ICU。它包含(除其他外)在时区之间转换的函数。请参阅TimeZone
类的留档。
例如,您可以创建一个时区对象:
TimeZone *tz = TimeZone::createTimeZone("America/Los_Angeles");
然后,您可以使用getOffset
等方法。
另请参阅ICU时区用户指南和此完整示例。
我找到了使用Boost的解决方案,但似乎有点迂回。它使用以下步骤:
使用示例程序可能更清楚:
#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;
}
示例使用和输出:
$ ./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
旧问题的新信息:
有一个新的开源时区库,它将完全解析您的IANA数据库的本地副本(包括所有历史数据甚至闰秒)。需要C 11或C 14编译器。您可以随时使用它来查找有关任何时区的详细信息。有关此库的详细信息包含在上面的链接中。
一个示例程序是:
#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';
}
它只是为我输出:
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
此输出解释如下:
>
在我回答这个问题的当天,“美国/Los_Angeles”的UTC偏移量为-7小时,时区的缩写为PDT。这与该地区的“标准时间”偏移1小时。此偏移量和缩写至少在此UTC时间点范围内有效:[2015-03-08 10:00:00,2015-11-01 09:00:00)。
提出此问题的当天,“America/Los_Angeles”的UTC偏移量为-8小时,时区的缩写为PST。这与该地区的“标准时间”无关。此偏移量和缩写至少在此UTC时间点范围内有效:[2014-11-02 09:00:00,2015-03-08 10:00:00)。
这是一个github项目,欢迎拉取请求以帮助将其移植到尽可能多的C 11/14平台。