【问题标题】:Get current GMT offset for a specific timezone获取特定时区的当前 GMT 偏移量
【发布时间】:2015-01-03 17:06:57
【问题描述】:

给定本地时区以外的特定时区(例如America/Los_Angeles),我如何找到该时区的当前 GMT 偏移量?目的是针对 DST 更改进行这项工作。也就是说,洛杉矶的 GMT 偏移量为 -8,在夏令时期间调整为 -7。

一些other answers 建议操纵TZ 环境变量,这会影响localtime 之类的函数返回,但我想要一个不会与环境变量混淆的解决方案(例如不可重入)。

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

【问题讨论】:

    标签: c++ timezone


    【解决方案1】:

    您可以考虑的一种方法是使用ICU。它包含(除其他外)在时区之间转换的功能。见the documentation for the TimeZone class

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

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

    然后您可以使用getOffset 之类的方法。

    另请参阅ICU Time Zone User Guidethis complete example

    【讨论】:

      【解决方案2】:

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

      • 加载一个time zone database,它可以转换一个时区名称,其中包含有关 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
      

      【讨论】:

      • 这里的问题是Boost's time zone file 已经严重过时了。当它准确时,它只对当前区域规则准确。它是平坦的,就像 POSIX 区域一样。 The real time zone database 包含有关时区规则如何随时间变化的丰富历史。
      【解决方案3】:

      旧问题的新信息:

      有一个新的开源timezone library完全解析IANA database 的本地副本(包括所有历史数据甚至闰秒)。需要 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
      

      这个输出解释如下:

      • 在我回答这个问题的那天,“America/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 project,欢迎提出请求以帮助将其移植到尽可能多的 C++11/14 平台。

      【讨论】:

        猜你喜欢
        • 2020-08-17
        • 2012-11-28
        • 1970-01-01
        • 2022-11-25
        • 1970-01-01
        • 2012-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多