我正在尝试将std::time_point
保存到std::stream
中并将其读回。一个问题是,使用标准函数会在某个地方"损失"一个小时。也就是说,我读书的时间比我写作的时间晚了一个小时。我怀疑我需要在某个地方设置夏令时。我编写了一个小程序,可以将时间打印到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(夏令时)突然不相等,时间也不相等。
我在Mac OS X 10.8.2上使用的是带有XCode46-DP2的libc++。我使用的clang++版本是Apple clang version 4.1
和clang version 3.2 (trunk 167239)
我想我的问题是:A) 至于1小时的差异,这是我库中的错误还是我没有正确使用标准函数?(后者不会让我感到惊讶…)
B) 当我取消对程序末尾的三行的注释时,代码发生了什么?这在我看来像个bug。有人想在他们的平台上试试吗?
我认为我们看到了%Z
说明符的一个错误,可能还有%z
说明符,还不确定。
我会进一步调查这些错误的原因。然而,我想继续发帖,为你找到一个变通办法。我相信,如果你对输入tm
进行零初始化,并始终假设它是关于你的本地时区的,那么你就会消除你的错误:
std::tm time_in{0};