【发布时间】:2019-12-09 18:31:01
【问题描述】:
问题
我想将作为字符串 (UTC) 给出的日期时间解析为自 epoch 以来的秒数。示例(见EpochConverter):
2019-01-15 10:00:00 -> 1547546400
问题
直接的解决方案,在一个非常相关的问题C++ Converting a time string to seconds from the epoch 中也被接受,使用std::string -> std::tm -> std::time_t 使用std::get_time 然后std::mktime:
std::tm tm;
std::stringstream ss("2019-01-15 10:00:00");
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
std::time_t epoch = std::mktime(&tm);
// 1547546400 (expected)
// 1547539200 (actual, 2 hours too early)
但std::mktime 似乎由于时区的原因而弄乱了时间。我正在执行来自UTC+01:00 的代码,但我们当时也有夏令时,所以这里是+2。
tm 在std::get_time 之后为hour 字段显示15。一进入std::mktime就会乱七八糟。
同样,字符串将被解释为 UTC 时间戳,不应涉及任何时区。但我想出的所有解决方案似乎都将其解释为本地时间戳并为其添加偏移量。
限制
对此我有一些限制:
- C++17
- 独立于平台/编译器
- 没有环境变量破解
- 没有外部库(如 boost)
尽管为了问答而发布涉及这些问题的答案,但我不会接受。
研究
我找到了各种尝试来解决这个问题,但没有一个符合我的要求:
-
std::mktime(如上所述),因为它假定为当地时间,所以弄乱了时间 -
strptime,在我的平台上不可用,不属于标准 -
timegm(这正是我所需要的),与平台无关 -
_mkgmtime,与平台无关 -
boost::posix_time::from_iso_string,是一个外部库 -
std::chrono::date::parse,不适用于 C++17 - 用
tzset清除并重置时区变量,使用环境变量hacking - 使用
mktime(localtime(&timestamp)) - mktime(gmtime(&timestamp))手动抵消偏移量,计算出错误的偏移量,因为它不考虑 DST(在我的平台上为 1 小时,但需要 2 小时)
【问题讨论】:
-
From this
std::mktimereference: "如果std::tm对象是从std::get_time...获取的,tm_isdst的值是不确定的,需要在调用mktime之前显式设置。”所以从那开始。 -
@Someprogrammerdude 但这需要我知道 DST 是否处于活动状态。对于我想随时随地在世界各地运行的程序来说,情况并非如此。对我来说这听起来没有必要,因为我根本不想涉及任何时区,日期字符串是 UTC,也应该用 UTC 解释,不应该涉及偏移量。这就是为什么我认为
std::mktime是一种不好的方法,因为它假定为当地时间。感谢您的意见:)
标签: c++ date utc epoch datetime-parsing