I have made two simple functions that can serialize and deserialize a time_t to a iso 8601 string format:
#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);
}
Now this almost works. I have two testcases where I check if this function works using boost unit test framework:
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."
);
}
How all the values are correct except for the hour. Which is off by one. The output of this test case:
Why is the hour of by one? And how can I fix this issue?
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.