【问题标题】:Strange behaviour when printing/reading time打印/阅读时间时的奇怪行为
【发布时间】:2012-11-29 10:16:18
【问题描述】:

我正在尝试将std::time_point 保存到std::stream 中并读回。一个问题是在某处使用标准函数会“损失”一个小时。即,我阅读的时间比我写作的时间晚 1 小时。我怀疑我需要在某个地方设置夏令时。我编写了一个小程序,将时间打印到std::stringstream 并读回。

#include <iomanip>
#include <iostream>
#include <sstream>

#include <chrono>
#include <ctime>

using std::chrono::system_clock;
namespace chrono = std::chrono;

void test();

int main(int argc, char** argv)
{
    std::stringstream ss;

    auto start = system_clock::now();

    std::time_t ts = system_clock::to_time_t(start);

    std::tm time_out = *std::localtime(&ts);
    ss << std::put_time(&time_out, "%Y-%m-%d %H:%M:%S %Z") << '\n';

    std::cout << ss.str() << std::endl;

    std::tm time_in;
    ss >> std::get_time(&time_in, "%Y-%m-%d %H:%M:%S %Z");

    std::cout << "Are time dsts equal? : " <<
    (time_out.tm_isdst == time_in.tm_isdst) << '\n';

    std::time_t rawTime = std::mktime(&time_in);
    auto end = std::chrono::system_clock::from_time_t(rawTime);

    std::cout << "Are time points equal? : " << (start == end) << '\n';

    // print the trouble makers
    std::time_t start_time = system_clock::to_time_t(start);
    std::time_t end_time = system_clock::to_time_t(end);

    std::cout << "times: \n"
    << '\t' << std::put_time(std::localtime(&start_time), "%c %z") << '\n'
    << '\t' << std::put_time(std::localtime(&end_time), "%c %z") << '\n';

    // this is a source of strange behaviour...
//    std::cout << "Difference: "
//    << chrono::duration_cast<chrono::seconds>(start - end).count()
//    << std::endl;

    return 0;
}

最奇怪的是程序打印了以下内容:

Are time dsts equal? : 1
Are time points equal? : 0
times: 
Tue Dec 11 19:26:24 2012 +0000
Tue Dec 11 19:26:24 2012 +0000

当我在程序末尾取消注释 3 行(打印时间点之间的差异)时,结果是:

Are time dsts equal? : 0
Are time points equal? : 0
times: 
Tue Dec 11 19:29:40 2012 +0000
Tue Dec 11 18:29:40 2012 +0000
Difference: 3600

请注意,dst(夏令时)突然不相等,时间也不相等。

我在带有 XCode46-DP2 的 Mac OS X 10.8.2 上使用 libc++。我使用的 clang++ 版本是 Apple clang version 4.1clang version 3.2 (trunk 167239)

我想我的问题是: A)关于 1 小时的差异,这是我的库中的错误还是我没有正确使用标准函数? (后者不会让我感到惊讶...)

B) 当我取消注释程序末尾的三行时,代码发生了什么?这对我来说似乎是一个错误。有人愿意在他们的平台上试用吗?

【问题讨论】:

标签: c++ time c++11 timezone chrono


【解决方案1】:

我认为我们正在查看带有 %Z 说明符的错误,也许还有带有 %z 说明符的错误,目前还不确定。

我会更多地调查这些错误的原因。但是,我想继续发布并为您提供解决方法。我相信,如果您将输入 tm 零初始化,并始终假设它与您当地的时区相关,那么您将消除错误:

std::tm time_in{0};

【讨论】:

  • 谢谢,效果很好。我使用的是time_in.is_dst = 0,效果也很好。
  • 在相关说明中,您会推荐哪种“时间类型”作为时间戳?我将它用于缓存中的条目,并希望能够丢弃旧条目。我正在使用time_t timestamp = system_clock::to_time_t(system_clock::now()) 创建时间戳,但我不确定它是否是最佳选择。
  • 这取决于您的精度需求。但是在 Mac OS X 10.8.2 上,如果你在 64 位模式下编译,这是默认的,time_t 的精度为秒并占用 64 位。 system_clock::time_point 也是一个合适的时间戳,同样占用64位,精度为微秒。如果您需要精确到纳秒的时间戳,那么在这个平台上您可以使用high_resolution_clock::time_point,它也是 64 位。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多