I am trying to parse UTC ECMA date format strings into a std::chrono::system_clock::time_point
on Windows.
My plan:
scanf
to load the string into a struct tm
_mkgmtime
to turn that into a time_t
(I am using _mkgmtime for this, because it uses UTC time, unlike something like mktime
, which uses local time).std::chrono::system_clock::from_time_t
to convert to a time_point
However, step 2 is always returning -1 for me, giving me bogus values for step 3.
The tm
struct seems valid, so I'm not sure what I'm doing wrong.
#include <chrono>
#include <iostream>
using namespace std;
int main() {
string timeStr = "2020-12-01T06:06:48Z";
struct tm tm = {0};
float s;
if (sscanf_s(timeStr.c_str(), "%d-%d-%dT%d:%d:%fZ", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &s) == 6) {
tm.tm_sec = static_cast<int>(s);
time_t t = _mkgmtime(&tm);
cout << "YEAR: " << tm.tm_year << endl; // 2020
cout << "MON: " << tm.tm_mon << endl; // 12
cout << "MDAY: " << tm.tm_mday << endl; // 1
cout << "HOUR: " << tm.tm_hour << endl; // 6
cout << "MIN: " << tm.tm_min << endl; // 6
cout << "SEC: " << tm.tm_sec << endl; // 48
cout << "TIME: " << t << endl; // -1
// TODO once this is solved:
auto tp = chrono::system_clock::from_time_t(t);
}
}
Compiler is MSVC 2019, C++17, x64. I cannot upgrade to C++20, or else I would use the new chrono tools for this.
In a tm
structure the member tm_year
is the number of years since 1900. Feeding in 2020 means you're actually providing year 3920.
It looks like _mkgmtime
hates that year. On my system _mkgmtime64
doesn't appear to work either. It should fit in a 64 bit time_t
, but definitely out of range for the 32 bit version. I can't find a clear-cut, documented reason for 3920 to be rejected or a cut-off point after which the function gives up. Make sure you have a 64 bit time_t
.
But none of that matters in this case since we want the year 2020. Adding
tm.tm_year -= 1900;
tm.tm_mon -= 1; // valid range 0 to 11, not 1 to 12
before converting will fix things up.