首页 > 解决方案 > 为什么使用 %z 格式的 std::put_time(std::gmtime 会为 UTC 返回 +0100?

问题描述

我在下面有这个小例子,它给了我不明白的结果。

#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 为 UTC 输出提供 +0100 而不是 +0000?我缺少逻辑的哪一部分?

例如,在http://ideone.com/IspjpG上运行它总是给出 +0000。

标签: c++c++11

解决方案


std::tm由返回的类std::gmtime并且std::localtime不包含时区信息,除了夏令时是否生效。对于gmtime,它永远不会生效,对于localtime,它取决于当前的语言环境和时间。

%Z格式说明符std::put_time使用当前语言环境获取时区信息。当前活动的语言环境不受std::tm作为参数给出的对象的影响。

因此,在第一种情况下,您打印本地时间以及有关本地时区的信息(启用 DST)。在第二种情况下,您打印 UTC 时间以及有关本地时区的信息(禁用 DST)。

我们可以得出结论,使用%zand%Z打印来自其他时区而不是当前本地时区的时间是不正确的。坦率地说,我认为它是std::put_time接口(以及包装的接口)中的一个缺陷std::strftimestd::put_time即无法将时区信息传递给函数,但可能会意外打印可能与std::tm正在打印的实例无关的时区。

要获得正确的输出,您应该使用:

ss2 << std::put_time(std::gmtime(&currentTime2),
    "%Y-%m-%dT%H:%M:%S +0000 UTC");

推荐阅读