c++functiondatetimetimemktime

C++ - Running same mktime() logic in 2 different ways giving unexpected result


I am converting a time in string to long time using strptime() and mktime. Strangely, using the same code in two different ways is giving different results. The values of struct tm is same in both the case though.

Please tell me what am I doing wrong.

Type 1

int main()
{
    string time = "2023-03-02 00:00:00";
    struct tm tm;
    strptime(time.c_str(), "%Y-%d-%m %H:%M:%S", &tm);   //it is supposed to give you value decreased by 1900 so if it gives you 113 it means the year is 2013. Month will also be decreased by 1, i.e. if it gives you 1, it is actually February. Just add these values:
    //mktime expects the value given by strptime itslf. No need to do any modifications.
    time_t t = mktime(&tm);
    cout<<"tm_sec: "<<tm.tm_sec<<endl;
    cout<<"tm_min: "<<tm.tm_min<<endl;
    cout<<"tm_hour: "<<tm.tm_hour<<endl;
    cout<<"tm_mday: "<<tm.tm_mday<<endl;
    cout<<"tm_mon: "<<tm.tm_mon<<endl;
    cout<<"tm_year: "<<tm.tm_year<<endl;    
    cout<<"tm_wday: "<<tm.tm_wday<<endl;
    cout<<"tm_yday: "<<tm.tm_yday<<endl;
    cout<<"tm_isdst: "<<tm.tm_isdst<<endl;
    cout<<t<<endl;
    return 0;
}

This runs as expected (t=1675382400)

Type 2

time_t convert_datetime_string_to_long_time(string time)
    {
        //convert string time to long unix time
        struct tm tm;
        strptime(time.c_str(), "%Y-%d-%m %H:%M:%S", &tm);   //it is supposed to give you value decreased by 1900 so if it gives you 113 it means the year is 2013. Month will also be decreased by 1, i.e. if it gives you 1, it is actually February. Just add these values:
        //mktime expects the value given by strptime itslf. No need to do any modifications.
        
        cout<<"tm_sec: "<<tm.tm_sec<<endl;
        cout<<"tm_min: "<<tm.tm_min<<endl;
        cout<<"tm_hour: "<<tm.tm_hour<<endl;
        cout<<"tm_mday: "<<tm.tm_mday<<endl;
        cout<<"tm_mon: "<<tm.tm_mon<<endl;
        cout<<"tm_year: "<<tm.tm_year<<endl;    
        cout<<"tm_wday: "<<tm.tm_wday<<endl;
        cout<<"tm_yday: "<<tm.tm_yday<<endl;

        time_t t = mktime(&tm);
        return t;
    }
int main() {
    time_t ans = convert_datetime_string_to_long_time("2023-03-02 00:00:00");
    cout<<ans<<endl;

    return 0;
}

The ans here =-1

How is this possible???


Solution

  • tm is uninitialized and you only initialize some of the fields. mktime is reading the uninitialized fields which makes the program have undefined behavior.

    Make sure to initialize it to get the expected result:

    struct tm tm{}; // <- now initialized
    // or:
    struct tm tm{.tm_isdst = -1};
    

    Note: The function should return a std::time_t, not a long.