Why I got 1 hour wrong when converting time string to tm with strptime?

Viewed 73

I am using strptime() to convert a time string into *tm

Here is my code

#include <time.h>
#include <iostream>
using namespace std;

int main() {
    string ts("2023-12-30 22:50:50");
    struct tm ti;
    strptime(ts.c_str(), "%F %T", &ti);
    cout << "time string: " << ts << endl
         << "ti: " << (ti.tm_year+1900) << "-" << (ti.tm_mon+1)
         << "-" << ti.tm_mday << " " << ti.tm_hour << ":"
         << ti.tm_min << ":" << ti.tm_sec << endl;
    return 0;
}

Here is what I got

time string: 2023-12-30 22:50:50
ti: 2023-12-30 21:50:50

For more information: my timezone should be -0600 (America center time), but it shows -0500 when I display with "date '+%Y-%m-%d %H:%M:%S %z". I thought this is caused by day-light-saving. Am I wrong? However 2023-12-30 is not in day-light-saving time.

Update: my problem was solved by setting tm_isdst=-1 as suggested in how-to-neatly-initialize-struct-tm-from-ctime. The reason for the problem is strptime() does not set tm_isdst in struct tm, but mktime() requires this information. Without tm_isdst=-1, I randomly got correct or wrong time when running the same code on different machines, or running it on the same machine at different time.

Here is the correct code

#include <time.h>
#include <iostream>
using namespace std;

int main() {
    string ts("2023-12-30 22:50:50");
    struct tm ti;
    strptime(ts.c_str(), "%F %T", &ti);
    ti.tm_isdst = -1;
    cout << "time string: " << ts << endl
         << "ti: " << (ti.tm_year+1900) << "-" << (ti.tm_mon+1)
         << "-" << ti.tm_mday << " " << ti.tm_hour << ":"
         << ti.tm_min << ":" << ti.tm_sec << endl;
    return 0;
}

Output from the above code

time string: 2023-12-30 22:50:50
ti: 2023-12-30 22:50:50
1 Answers

I changed the first parameter of strptime to tm.c_str(). Here isall the code for your reference.

#include <time.h>
#include <iostream>
using namespace std;
int main() {
    string str_time("2023-12-30 22:50:50");
    struct tm ti;
    strptime(str_time.c_str(), "%F %T", &ti);
    std::cout << "time string: " << str_time << endl
            << "ti: " << (ti.tm_year+1900) << "-" << (ti.tm_mon+1) << "-" << ti.tm_mday << " " << ti.tm_hour << ":" << ti.tm_min << ":" << ti.tm_sec << endl;
    return 0;
}

build with g++ 9.4.0

gxie@ubuntu:~/test $ g++ test.cpp
gxie@ubuntu:~/test $ ./a.out
time string: 2023-12-30 22:50:50
ti: 2023-12-30 22:50:50
Related