C++20 introduces std::chrono::from_stream()
to parse date/time from a string and store it in a std::chrono::time_point
. For example:
std::stringstream ss("2018-12-09T00:00:00+0130");
std::chrono::time_point<std::chrono::utc_clock> tp;
if (std::chrono::from_stream(ss, "%FT%T%z", tp))
{
std::cout << "Time point: " << tp << '\n';
}
else
std::cout << "Not a valid timestamp\n";
However, GCC prior to version 14, as well as clang up to at least version 20.1, have not implemented this. Attempts to use from_stream
result in a compiler error:
error: ‘from_stream’ is not a member of ‘std::chrono’
What workarounds are available in these versions? I can easily parse year/month/day/hour/minute/second/UTC offset (hours/minutes) into individual variables or a std::tm
, but there doesn’t seem to be a straightforward way to construct a time_point
from that.
system_clock
has from_time_t()
(utc_clock
doesn’t), but that requires me to use legacy C code, which has its own flaws such as not being thread-safe.
How can I construct a std::chrono::time_point
from pre-parsed field values, in a way that’s portable and doesn’t require new dependencies?
If you already have a struct tm
with requested fields, you can convert it to a time_point
of system_clock
as follows:
constexpr std::chrono::sys_seconds from_tm(const std::tm& t)
{
using namespace std::chrono;
const auto y = static_cast<year>(t.tm_year + 1900);
const auto m = static_cast<month>(t.tm_mon + 1);
const auto d = static_cast<day>(t.tm_mday);
const hours h{t.tm_hour};
const minutes m{t.tm_min};
const seconds s{t.tm_sec};
sys_seconds res = sys_days{y/m/d};
res = res + h + m + s;
return res;
}
You can use std::chrono::clock_cast
to convert the result to a time point of a different, compatible clock. For example:
std::chrono::time_point<std::chrono::utc_clock> tp
= std::chrono::clock_cast<std::chrono::utc_clock>(res);