Question
I want to parse a date-time given as string (UTC) into seconds since epoch. Example (see EpochConverter):
2019-01-15 10:00:00 -> 1547546400
Problem
The straightforward solution, which is also accepted in a very related question C++ Converting a time string to seconds from the epoch goes std::string -> std::tm -> std::time_t
using std::get_time
and then std::mktime
:
std::tm tm;
std::stringstream ss("2019-01-15 10:00:00");
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
std::time_t epoch = std::mktime(&tm);
// 1547546400 (expected)
// 1547539200 (actual, 2 hours too early)
But std::mktime
seems to mess up the hours due to timezone. I am executing the code from UTC+01:00
, but we also had DST at that date, so its +2
here.
The tm
shows 15
for the hour
field after std::get_time
. It gets messed up as soon as it enters std::mktime
.
So again, the string is to be interpreted as UTC timestamp, no timezones whatsoever should be involved. But all solutions I came up with seem to interpret it as local timestamp and add offsets to it.
Restrictions
I have some restrictions for this:
- C++17
- platform/compiler independent
- no environment variable hacking
- no external libraries (like boost)
Feel free to post answers involving those for the sake of Q&A though, but I wont accept them.
Research
I found various attempts to solve this problem, but none met my requirements:
std::mktime
(as mentioned above), messes up the time because it assumes local timestrptime
, not available on my platform, not part of the standardtimegm
(thats exactly what I would need), not platform independent_mkgmtime
, not platform independentboost::posix_time::from_iso_string
, is an external librarystd::chrono::date::parse
, not available with C++17- clear and reset the timezone variable with
tzset
, uses environment variable hacking - manually countering the offset with
mktime(localtime(×tamp)) - mktime(gmtime(×tamp))
, computes the wrong offset since it does not account for DST (1 hour on my platform but it would need to be 2 hours)
std::mktime
reference: "If thestd::tm
object was obtained fromstd::get_time
..., the value oftm_isdst
is indeterminate, and needs to be set explicitly before callingmktime
." So start with that. – Calkinsstd::mktime
is a bad approach to this, as it assumes local time. Thanks for your input though :) – Ootid