Converting a string_view to a time_point in C++20
published at 01.02.2024 17:52 by Jens Weller
Save to Instapaper Pocket
In one class I have a string_view which can represent various value types. One of them is a "date-time type", such as a std::time_t or std::chrono::time_point.
And I've decided to use time_point for now, and chrono has the convenient typedef sys_seconds for a type that holds time as seconds. And converting the string_view to said sys_seconds is easy with std::chrono::parse.
std::chrono::sys_seconds convertToTimePoint(std::string_view fmtstring) { std::chrono::sys_seconds syssec; std::istringstream in{std::string{raw_data}};//raw_data is a string_view in >> std::chrono::parse(fmtstring, syssec); return syssec; }
Unfortunately I have to use a stringstream as a means of conversion. My knowledge of chrono is a bit limited, I'd love to know if this goes without. Though, there is a different problem here: my current GCC does not support std::chrono::parse.
Howard Hinnant does provide the full implementation of chrono on github, so using this would be a good option. Though I don't want to install another library into my new and rather small project. I'd rather try to do the conversion over the already existing interfaces.
So until I can use chrono::parse in the GCC Version I use, the conversion needs to do a little detour over time_t with std::get_time:
std::chrono::sys_seconds convertToTimePoint(std::string_view fmtstring) { std::chrono::sys_seconds syssec; std::istringstream in{std::string{raw_data}};//raw_data is a string_view std::tm tm = {}; in >> std::get_time(&tm, fmtstring.data()); std::time_t time = std::mktime(&tm); syssec = std::chrono::time_point_cast< std::chrono::sys_seconds::duration>(std::chrono::system_clock::from_time_t(time)); return syssec; }
Also get_time needs an iostream, which then leads to turning the string_view in a string.
Looking at the code it feels right, but as my knowledge of C++20 and chrono is still a bit limited, I wonder if there is a better way.
Update: error handling
Once I started thinking about the code, I wondered on how to handle errors. Since the fmtstring is user provided, I should ad an inout parameter for error codes and/or maybe even the message or throw an exception. So before converting the time_t value to syssec, one should check in.good().
std::chrono::sys_seconds convertToTimePoint(std::string_view fmtstring) { std::chrono::sys_seconds syssec; std::istringstream in{std::string{raw_data}};//raw_data is a string_view std::tm tm = {}; in >> std::get_time(&tm, fmtstring.data()); std::time_t time = std::mktime(&tm);
if(in.good()) syssec = std::chrono::time_point_cast< std::chrono::sys_seconds::duration>(std::chrono::system_clock::from_time_t(time));
else throw std::runtime_error(std::string("Could not convert ") + raw_data + " to a date time value with format string " + fmtstring); return syssec; }
Join the Meeting C++ patreon community!
This and other posts on Meeting C++ are enabled by my supporters on patreon!