Reputation: 35
I have this code:
std::tm tm{};
std::istringstream str_stream("Wed"); // date
str_stream >> std::get_time(&tm, "%a"); // format date
std::time_t time = std::mktime(&tm); // equals -1
Also it do not work with "Sep" and %b, i. e. it do not work with chars. What I'm doing wrong?
Upvotes: 0
Views: 162
Reputation: 35154
Your call will probably write successfully into t->tm_wday
, yet when using mktime afterwards, the value in time->tm_wday
is ignored:
std::mktime
... time->tm_wday and time->tm_yday are ignored. The values in time are permitted to be outside their normal ranges. ...
Hence, everything you write into tm
is ignored, the result cannot be represented as time_t
, and the return value is thus -1
.
In contrast to mktime
, std::put_time
uses the respective values, but reinterprets them for the output (such that February
might turn into Feb
):
int main ()
{
std::tm t = {};
istringstream ss("Thursday February");
ss >> std::get_time(&t, "%a %b");
if (ss.fail()) {
cout << "invalid date value." << endl;
}
else {
std::cout << "Date: " << std::put_time(&t, "%a %b") << endl;
}
return 0;
}
Output:
Date: Thu Feb
Upvotes: 0
Reputation: 30115
If you inspect the contents of tm
it should be what you expect.
get_time
with %a
will parse into tm_wday
.
However mktime
does not use tm_wday
and tm_yday
at all, using the other fields exclusively. Infact, mktime
actually sets those fields (this is why the tm input can not be const
) based on the others.
Thus you are effectively passing a bunch of zeros to it, notably tm_year
, and with time_t
on many plaforms being seconds since 1970, and allthough often signed, they consider times before 1970 invalid.
For example with MSVC, time_t
is a 64bit signed integer, but mktime is documented to only be valid for "January 1, 1970 to 23:59:59, December 31, 3000"
Upvotes: 2