我正在将当前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_tUnix 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

07-28 00:54
查看更多