Почему std :: put_time (std :: gmtime с форматом% z возвращает +0100 для UTC? - PullRequest
1 голос
/ 08 октября 2019

У меня есть маленький пример ниже, который дает мне результаты, которые я не понимаю.

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

int main() {
    auto currentTime = std::time(nullptr);
    auto currentTime2 = std::time(nullptr);

    std::stringstream ss;
    std::stringstream ss2;

    ss << std::put_time(std::localtime(&currentTime), "%Y-%m-%dT%H:%M:%S %z %Z");
    ss2 << std::put_time(std::gmtime(&currentTime2), "%Y-%m-%dT%H:%M:%S %z %Z");
    std::cout << " time now local = " << ss.str() << std::endl;
    std::cout << " time now gm    = " << ss2.str() << std::endl;
}

В Windows (VS2017) это дает мне:

 time now local = 2019-10-08T16:25:17 +0200 W. Europe Summer Time
 time now gm    = 2019-10-08T14:25:17 +0100 W. Europe Standard Time

В Mac(XCode 10) это дает мне:

 time now local = 2019-10-08T16:25:17 +0200 CEST
 time now gm    = 2019-10-08T14:25:17 +0100 UTC

Может ли кто-нибудь объяснить мне, почему% z дает +0100 для выходов UTC вместо +0000? Какую часть логики мне не хватает?

Запуск этого на http://ideone.com/IspjpG, например, всегда дает + 0000.

1 Ответ

1 голос
/ 08 октября 2019

Класс std::tm, возвращаемый std::gmtime и std::localtime, не содержит информацию о часовом поясе, кроме того, действует ли переход на летнее время. Для gmtime оно никогда не действует, а для localtime это зависит от текущей локали и времени.

%Z спецификатор формата std::put_time использует текущую локаль для информации о часовом поясе. На текущую активную локаль не влияет объект std::tm, заданный в качестве аргумента.

Так что в первом случае вы печатаете местное время с информацией о местном часовом поясе (с включенным DST). А во втором случае вы печатаете время UTC с информацией о местном часовом поясе (с отключенным DST).

Мы можем сделать вывод, что использование %z и %Z неверно для печати времени из других часовых поясов, отличных от текущего местногоодин. Честно говоря, я считаю недостатком интерфейса std::put_time (и интерфейса std::strftime, который std::put_time оборачивается) то, что невозможно передать информацию о часовом поясе в функцию, но можно случайно напечатать часовой пояс, который может не иметь отношения к std::tm экземпляр печатается.

Для правильного вывода вы должны использовать:

ss2 << std::put_time(std::gmtime(&currentTime2),
    "%Y-%m-%dT%H:%M:%S +0000 UTC");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...