我做了两个简单的函数,可以将time_t序列化和反序列化为iso 8601字符串格式:
#include <stdexcept>
#include <boost/format.hpp>
std::string time_t_to_iso_format(std::time_t time)
{
char buf[sizeof "2017-05-01T00:00:00"];
strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S", gmtime(&time));
return std::string(buf);
}
std::time_t iso_format_to_time_t(std::string& iso_time)
{
auto error_message = boost::format{"Invalid iso_time: %1%"} % iso_time;
if (iso_time.length() != std::string("2017-05-01T00:00:00").length())
{
throw std::invalid_argument(error_message.str());
}
struct tm t = { 0 };
auto c_str = iso_time.c_str();
t.tm_sec = std::stoi(std::string(c_str + 17));
t.tm_min = std::stoi(std::string(c_str + 14));
t.tm_hour = std::stoi(std::string(c_str + 11));
t.tm_mday = std::stoi(std::string(c_str + 8));
t.tm_mon = std::stoi(std::string(c_str + 5)) - 1;
t.tm_year = std::stoi(std::string(c_str)) - 1900;
return mktime(&t);
}
现在这几乎可以了。我有两个测试用例,我使用boost单元测试框架检查此函数是否有效:
BOOST_AUTO_TEST_CASE(time_t_tools)
{
auto iso_time = std::string("2017-05-01T23:15:29");
auto converted = iso_format_to_time_t(iso_time);
auto round_trip = time_t_to_iso_format(converted);
BOOST_REQUIRE_MESSAGE(
iso_time.compare(round_trip) == 0,
"Iso times are not equal: " << iso_time << ", " << round_trip << ". It didn't survive the round-trip iso time -> time_t -> iso time."
);
iso_time = std::string("1980-12-04T14:00:10");
converted = iso_format_to_time_t(iso_time);
round_trip = time_t_to_iso_format(converted);
BOOST_REQUIRE_MESSAGE(
iso_time.compare(round_trip) == 0,
"Iso times are not equal: " << iso_time << ", " << round_trip << ". It didn't survive the round-trip iso time -> time_t -> iso time."
);
}
除小时外,所有值的正确性如何。哪个是一个人。这个测试用例的输出:
为什么一小时呢?我该如何解决这个问题呢?
fatal error: in "time_t_tools": Iso times are not equal: 2017-05-01T23:15:29, 2017-05-01T22:15:29. It didn't survive the round-trip iso time -> time_t -> iso time.