提问者:小点点

获取特定时区的当前GMT偏移量


给定本地时区以外的特定时区(例如America/Los_Angeles),如何找到该时区的当前GMT偏移量?其目的是使此工作与DST变化有关。也就是说,洛杉矶的GMT偏移量为-8,在夏令时调整为-7。

其他一些答案建议操作TZ环境变量,它会影响localtime返回的函数,但我想要一个不与环境变量混淆的解决方案(例如,不可重入)。

所有这些信息似乎都可以通过zdump/usr/share/zoneinfo上获得,但我如何从C中获取这些信息并不明显。


共3个答案

匿名用户

您可以考虑的一种方法是使用ICU。它包含(除其他外)在时区之间转换的函数。请参阅TimeZone类的留档。

例如,您可以创建一个时区对象:

TimeZone *tz = TimeZone::createTimeZone("America/Los_Angeles");

然后,您可以使用getOffset等方法。

另请参阅ICU时区用户指南和此完整示例。

匿名用户

我找到了使用Boost的解决方案,但似乎有点迂回。它使用以下步骤:

  • 加载一个时区数据库,该数据库可以转换包含DST开始和结束时间信息的时区名称。这CSV几百行,很容易获得。
  • 通过查找所述数据库,使用GMT和特定时区获取当前时间
  • 取两次的差值,得到GMT偏移量

使用示例程序可能更清楚:

#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平台。