在 C++ 中从字符串中读取 GMT 时间

Oth*_*oun 2 c++ time mktime

我将当前 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");
Run Code Online (Sandbox Code Playgroud)

稍后我想做相反的操作,从字符串流中读取 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)));
Run Code Online (Sandbox Code Playgroud)

下面的代码中缺少一些内容,因为解码的时间从未转换为 GMT,因此由于我的本地时区,我最终得到 1 小时的时差

PS: 只能使用标准库,并且不能更改日期字符串格式

How*_*ant 5

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);
Run Code Online (Sandbox Code Playgroud)

尚未有供应商实现 C++20 的这一部分,但namespace date.

在 C++20 之前的 C++ 中,没有库支持执行此操作。

仅使用标准库可以做的最好的事情是将字段解析为tmusing std::get_time(如您的问题所示),然后将该{y, m, d, h, M, s}结构转换为使用您自己的数学,以及Unix 时间time_t的假设(通常是正确std::time_t的)精确到秒。

以下是公共领域日历算法的集合,可以帮助您做到这一点。这不是第三方库。这是一本用于编写您自己的日期库的食谱。

例如:

#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;
}
Run Code Online (Sandbox Code Playgroud)

上面的链接对该算法和单元测试进行了非常深入的描述,以确保它在+/-数百万年的范围内工作。

上面的内容本质上是在 Linux 和 bsd 平台上发布to_time_t的可移植版本。timegm在 Windows 上也调用此函数_mkgmtime。