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

时间:2019-07-04 09:02:14

标签: 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");

稍后我想做相反的操作,将字符串流中的时间读取为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:只能使用标准库,并且不能更改日期字符串格式

3 个答案:

答案 0 :(得分:0)

tm结构不存储时区信息,默认情况下使用本地时区的是mktime。 在this thread之后,最好的选择是使用:

#include "time.h" 
timestamp = mktime(&tm) - timezone; //or _timezone

如果timezone_timezone对您的编译器可用。链接答案中的一条警告警告说,这可能会引起夏时制问题,但不适用于GMT。

答案 1 :(得分:0)

C ++ 2a草案(我们希望'a'为'0')规范具有实现此目的的便捷方法:

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 ++ 2a的这一部分,但是有示例实现here in namespace date

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

仅使用 标准库,最好的做法是使用tm(如您的问题所示)将字段解析为std::get_time,然后将其转换为{{ 1}}使用自己的数学结构构造为{y, m, d, h, M, s},并假设time_tUnix Time且假设精确到秒(通常是正确的)。

这里有collection of public domain calendrical algorithms可以帮助您做到这一点。这不是第三方库。这是一本用于编写自己的日期库的食谱。

例如:

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; } 本质上是Linux和bsd平台上附带的to_time_t的可移植版本。在Windows上也称为timegm

答案 2 :(得分:0)

我最近试图解决一个非常相似的问题。无论计算机的当前时区是什么,我都试图将字符串转换为特定时区。这是我提出并按预期工作的解决方案:

std::time_t from_time_str(std::string time_str) {
    std::stringstream ss;
    std::tm tm = {};
    ss << time_str;
    ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
    std::time_t t = std::mktime(&tm);
    std::tm* gm_tm = std::gmtime(&t);
    gm_tm->tm_isdst = false;
    std::time_t gm_t = std::mktime(gm_tm);
    std::time_t gm_offset = (gm_t - t);
    std::time_t real_gm_t = t - gm_offset;
    return real_gm_t;
}

这个想法是使用函数 gmtime 来获取时间戳的 gmtime 以便我们可以计算目标计算机时区的偏移量。然后我们减去偏移量以获得 GM 时间。

请注意,启用夏令时的任何时区都需要行 gm_tm->tm_isdst = false;,否则 gmtime 将使用夏令时偏移(1 小时关闭)计算,这不应该是计算实际的预期效果通用时间。