我将当前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:只能使用标准库,并且不能更改日期字符串格式
答案 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_t
是Unix 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 小时关闭)计算,这不应该是计算实际的预期效果通用时间。