найти разницу местного часового пояса с GMT в минутах - PullRequest
1 голос
/ 06 мая 2020

У меня часовой пояс в формате GMT ​​+ 09: 00 и GMT + 10: 00. Я использую Linux (Open Suse) и C ++ 17. Я пытаюсь узнать разницу между местным часовым поясом и GMT в минутах.

Вот мой пример программы.

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

Любой указатель, почему я получаю их отрицательно?

1 Ответ

1 голос
/ 06 мая 2020

Эти строки известны как часовые пояса POSIX и определены здесь . Это определение говорит о смещении UT C:

Если ему предшествует '-', часовой пояс должен быть к востоку от нулевого меридиана; в противном случае он должен быть западным (что может быть обозначено необязательным предшествующим '+').

Между тем std::put_time определено в терминах C / Posix strftime, в котором говорится о смещении :

% z заменяется смещением от UT C в формате ISO 8601 «-0430» (то есть на 4 часа 30 минут меньше UT C, к западу от Гринвича), или без символов, если часовой пояс не определяется. [tm_isdst]

Таким образом, существует одно соглашение для строк часового пояса posix (отрицательное означает восток начального меридиана), а другое - почти для всех остальных, включая другие части. of posix (отрицательное значение означает запад от нулевого меридиана).

Итак, ваш код действительно получает правильный ответ.

Fwiw, вот C + +17 бесплатных библиотек часовых поясов Posix с открытым исходным кодом, только для заголовков , которая может выполнять работу без изменения глобальной переменной среды 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
...