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!