ark0f
ark0f

Reputation: 35

Failed to parse date

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

Answers (2)

Stephan Lechner
Stephan Lechner

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

Fire Lancer
Fire Lancer

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

Related Questions