I'm trying to get the current year stored in a date from before 1970 using an std::chrono::time_point<std::chrono::system_clock>
, however I've run into an issue regarding the reading from its contents into a std::tm
struct.
I convert the time_point
to a time_t
first, after which I read its values to get the tm_year
value. However, when trying to do so, the code fails when using localtime_s
, however it succeeds when I'm using gmtime_s
. This is only for dates before 1-1-1970, dates after that work fine using both functions.
The code below reproduces the error. If terstGmTimeVsLocalTime
is called with utc=true
it works, if it is called with utc=false
it doesn't produce the correct output.
#include <iomanip>
#include <time.h>
#include <iostream>
void testGmTimeVsLocaltime(const bool& utc) {
// Create time
std::tm timeInfoWrite = std::tm();
timeInfoWrite.tm_year = 1969 - 1900; // Year to parse, here it is 1969
timeInfoWrite.tm_mon = 0;
timeInfoWrite.tm_mday = 1;
timeInfoWrite.tm_hour = 1;
timeInfoWrite.tm_min = 0;
timeInfoWrite.tm_sec = 0;
timeInfoWrite.tm_isdst = -1;
std::chrono::time_point<std::chrono::system_clock> timePoint = std::chrono::system_clock::from_time_t(utc ? _mkgmtime(&timeInfoWrite) : std::mktime(&timeInfoWrite));
// Convert to time_t
std::time_t timeT = std::chrono::system_clock::to_time_t(timePoint);
// Read values
std::tm timeInfoRead;
if (utc) {
gmtime_s(&timeInfoRead, &timeT);
} else {
localtime_s(&timeInfoRead, &timeT);
}
// Output result
std::cout << (timeInfoRead.tm_year + 1900) << '\n';
// Wait for input
std::getchar();
}
int main() {
testGmTimeVsLocaltime(true); // Set to false to show bug
return 0;
}
utc=true
outputs 1969, as would be expected. However, utc=false
outputs 1899 (presumably since an error occurs and tm_year
gets set to -1).
Is there anything I'm missing? The documentation doesn't specifically specify that localtime_s
should fail for dates before 1-1-1970.
I'm on Windows 10 x64 if it makes a difference.