我有一个字符串,根据某种格式将其转换为时间
const std::string format = "%Y-%m-%dT%H:%M:%S";
std::istringstream dateStream(date);
std::tm tm = {};
dateStream >> std::get_time(&tm, format.c_str());
然后我想给它添加一个偏移量 并将结果打印为字符串:
tm.tm_min += offset;
std::mktime(&tm);
std::ostringstream resultStream;
resultStream << std::put_time(&tm, format.c_str());
它似乎在这里工作 https://godbolt.org/z/q7svh51Y7
但是当我在本地系统上运行它时,我收到 2023-09-26T18:18:23 而不是 2023-09-26T17:18:23 您能帮忙解决这个问题吗?
最佳答案
问题在于 C API(mktime
、strftime
、strptime
等)将“故障时间”与“本地时间”混为一谈。 time”,并以有趣且意想不到的方式应用 UTC 偏移量。
有两种方法可以解决这个问题:
继续使用 C API,但添加:
std::tm tm = {}; tm.tm_isdst = -1; // Add this line
这有效。但这个 API 很难使用,这种类型的错误几乎肯定会再次袭击您。
使用 chrono 和 C++20。但是,如果您坚持使用 C++17,可以使用 free, open-source, header-only C++20 chrono preview library与 C++11/14/17 兼容,更安全、更易于使用,并且在时机成熟时可以轻松移植到 C++20。
#include "date/date.h" #include <chrono> #include <iostream> #include <sstream> std::string setOffsetForTime(const std::string& date, const std::chrono::seconds offset) { const std::string format = "%Y-%m-%dT%H:%M:%S"; std::istringstream dateStream(date); date::sys_seconds tm = {}; dateStream >> date::parse(format, tm); tm += offset; std::ostringstream resultStream; resultStream << date::format(format, tm); return resultStream.str(); } int main() { std::string dateString1 = "2023-09-26T11:48:23"; const std::chrono::minutes offset{330}; std::cout<< setOffsetForTime(dateString1, offset); return 0; }
正如您所看到的,新代码的结构与您已有的代码没有什么不同。但以下是重要的区别:
A.它使用类型安全的时间单位,例如分钟
和秒
,而不是int
。
B. sys_seconds 类型具有 UTC 时间点的语义。不涉及时区。如果您想要转换为本地时间,则需要在代码中显式执行,而不是隐式执行。
要将其移植到 C++20,您需要删除 #include "date/date.h"
并将几个 date::
更改为 std::计时::
。并且 format
字符串需要针对格式化语句稍作更改:"{:%Y-%m-%dT%H:%M:%S}"
.
关于c++ - 添加时间偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77229156/