我正在将当前GMT时间写为字符串,如下所示:
const std::time_t now = std::time(nullptr);
std::stringstream ss;
ss << std::put_time(std::gmtime(&now), "%Y-%m-%d %H:%M:%S");
稍后我想做相反的操作,从stringstream中读取时间为GMT,并将其与当前时间戳进行比较:
std::tm tm = {};
ssTimestamp >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
const std::time_t&& time = std::mktime(&tm);
const double timestampDiff((std::difftime(std::time(nullptr), time)));
以下代码中缺少某些内容,因为解码后的时间从未转换为格林尼治标准时间,因此由于本地时区的原因,我的时差为1小时
P.S:只能使用标准库,并且不能更改日期字符串格式
最佳答案
C++ 20规范具有实现此目的的便捷方法:
using namespace std::chrono;
sys_seconds tp;
ssTimestamp >> parse("%Y-%m-%d %H:%M:%S", tp);
std::time_t time = system_clock::to_time_t(tp);
尚未有供应商实现C++ 20的这一部分,但是有一个示例实现here in
namespace date
。在C++ 20之前的C++中,没有库支持执行此操作。
仅使用标准库可以做的最好的事情就是使用
tm
将字段解析为std::get_time
(如您的问题所示),然后使用您自己的数学将该{y, m, d, h, M, s}
结构转换为time_t
,并假设(通常是正确的) std::time_t
是Unix Time,精度为秒。这是一个collection of public domain calendrical algorithms可以帮助您做到这一点。这不是第三方图书馆。这是一本用于编写自己的日期库的食谱。
例如:
#include <ctime>
std::time_t
to_time_t(std::tm const& tm)
{
int y = tm.tm_year + 1900;
unsigned m = tm.tm_mon + 1;
unsigned d = tm.tm_mday;
y -= m <= 2;
const int era = (y >= 0 ? y : y-399) / 400;
const unsigned yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365]
const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
return (era * 146097 + static_cast<int>(doe) - 719468)*86400 +
tm.tm_hour*3600 + tm.tm_min*60 + tm.tm_sec;
}
上面的链接对该算法和单元测试进行了非常深入的描述,以确保它可以在+/-百万年的范围内工作。
上面的
to_time_t
本质上是Linux和bsd平台上附带的timegm
的可移植版本。在Windows上,此功能也称为_mkgmtime
。