以分钟为单位查找本地时区与格林尼治标准时间的差异

问题描述 投票:0回答:1

我的时区为GMT + 09:00和GMT + 10:00。我正在使用Linux(Open Suse)和C ++ 17。我正在尝试在几分钟内找出当地时区与格林尼治标准时间的差异。

这是我的示例程序。

static constexpr time_t const NULL_TIME = -1;

// returns difference in mintues
long tz_offset(time_t when = NULL_TIME) {
  if (when == NULL_TIME)
    when = std::time(nullptr);
  auto const tm = *std::localtime(&when);
  std::ostringstream os;
  os << std::put_time(&tm, "%z");
  std::string s = os.str();
  // s is in ISO 8601 format: "±HHMM"
  int h = std::stoi(s.substr(0, 3), nullptr, 10);
  int m = std::stoi(s[0] + s.substr(3), nullptr, 10);
  return h * 60 + m;
}

int main() {
  for (auto &timezone :  {"GMT+08:00", "GMT+09:30", "GMT+10:00", "GMT+10:30", "GMT+11:00"}) {
    setenv("TZ", timezone, 1);
    tzset();
    std::cout << "----------- TZ Changed to " << timezone << "---------------\n";
    std::cout << "difference in mins =" << tz_offset() << std::endl;
    auto tz_env_var = getenv("TZ");
    if (tz_env_var != nullptr) {
      std::cout << "TZ=" << tz_env_var << "\n";
    }
  }

  return 0;
}

但是我得到的是负面的差异,它们应该是正面的。

----------- TZ Changed to GMT+08:00---------------
difference in mins =-480
TZ=GMT+08:00
----------- TZ Changed to GMT+09:30---------------
difference in mins =-570
TZ=GMT+09:30
----------- TZ Changed to GMT+10:00---------------
difference in mins =-600
TZ=GMT+10:00
----------- TZ Changed to GMT+10:30---------------
difference in mins =-630
TZ=GMT+10:30
----------- TZ Changed to GMT+11:00---------------
difference in mins =-660
TZ=GMT+11:00

任何指针为什么我让它们成为负面的?

c++ linux c++17 timezone-offset chrono
1个回答
0
投票

这些字符串称为POSIX时区,为defined here。此定义说明了有关UTC偏移量的信息:

[如果前面带有'-',则时区应位于本初子午线以东;否则,它应该是向西的(可以用可选的前面的'+'表示)。

同时std::put_time是根据C / Posix strftime来定义的,它说了关于偏移量:

%z替换为ISO 8601格式'−0430'(表示4的UTC偏移量)比格林威治标准时间UTC晚30分钟),如果没有时间,则不限字符区域是可以确定的。 [tm_isdst]

总而言之,对于posix时区字符串有一个约定(负数表示在本初子午线以东),对于其他所有人,还有另一个约定,包括posix的其他部分(负数表示在本初子午线以西)。

所以您的代码实际上得到了正确的答案。

Fwiw,这是一个C++17 free, open-source, header-only Posix time zone library,可以在不更改全局环境变量TZ的情况下执行此作业,并且使用更简单的语法来做到这一点:

#include "date/ptz.h"
#include <chrono>
#include <iostream>

int
main()
{
    using namespace std::chrono;
    using date::operator<<;

    for (auto &timezone : {"GMT+08:00", "GMT+09:30", "GMT+10:00", "GMT+10:30", "GMT+11:00"})
    {
        auto offset = Posix::time_zone{timezone}.get_info(system_clock::now()).offset;
        std::cout << "difference is " << duration_cast<minutes>(offset) << '\n';
        std::cout << "TZ is " << timezone << "\n\n";
    }
}

输出:

difference is -480min
TZ is GMT+08:00

difference is -570min
TZ is GMT+09:30

difference is -600min
TZ is GMT+10:00

difference is -630min
TZ is GMT+10:30

difference is -660min
TZ is GMT+11:00
© www.soinside.com 2019 - 2024. All rights reserved.