Problem when converting from time_t to tm then back to time_t

4226 views c++
0

I have a time_t value of 1530173696 which represents Thursday, June 28, 2018 8:14:56 AM.

I want to round down the time to the nearest hour. Specifically, down to 1530172800, which represent Thursday, June 28, 2018 8:00:00 AM. So, my idea is to convert this time_t to a tm struct, and then assign its sec and min values to 0.

However, after I do that, and after I convert the modified tm back to a time_t value, the value I get is way off. I get a value of 1530158400 which represents Thursday, June 28, 2018 4:00:00 AM. That's 4 hours off. Even checking values of up to 8:59:59 AM still gives the rounded down value of 4:00:00 AM.

I wrote the code below to demonstrate the problem. I use VisulStudio 2017.

I don't understand what I am doing wrong. I appreciate any help. Thanks.

#include <iostream>
#include <time.h>

bool equalTMs(tm& tm1, tm& tm2);
void printTM(tm& myTM);

int main()
{
    tm myTM;
    time_t datetime = 1530173696;
    //datetime = 1530176399; // to check the time_t value of 8:59 AM
    gmtime_s(&myTM, &datetime);
    myTM.tm_sec = 0;
    myTM.tm_min = 0;
    time_t myTime_T = mktime(&myTM);

    tm sanityCheckTM;
    time_t roundedDownToNearestHour = 1530172800;
    gmtime_s(&sanityCheckTM, &roundedDownToNearestHour);
    time_t sanityCheckTimeT = mktime(&sanityCheckTM);

    std::cout << "datetime: " << datetime << std::endl;
    std::cout << "myTime_T: " << myTime_T << std::endl;
    std::cout << std::endl;
    std::cout << "roundedDownToNearestHour: " << roundedDownToNearestHour << std::endl;
    std::cout << "sanityCheckTimeT: " << sanityCheckTimeT << std::endl;
    std::cout << std::endl;
    std::cout << "myTM and sanityCheckTM equal? " << (equalTMs(myTM, sanityCheckTM) ? "true" : "false") << std::endl;

    std::cout << "\nmyTM:-\n\n";
    printTM(myTM);
    std::cout << "\nsanityCheckTM:-\n\n";
    printTM(sanityCheckTM);
    std::cout << "\n";

    time_t _time_t = 1530158400;
    tm _tm;
    gmtime_s(&_tm, &_time_t);
    std::cout << "_time_t: " << _time_t << std::endl;
    std::cout << "_tm and sanityCheckTM equal? " << (equalTMs(_tm, sanityCheckTM) ? "true" : "false") << std::endl;

    std::cout << "\n_tm:-\n\n";
    printTM(_tm);

}

void printTM(tm& myTM)
{
    std::cout << "tm_sec: " << myTM.tm_sec << std::endl;
    std::cout << "tm_min: " << myTM.tm_min << std::endl;
    std::cout << "tm_hour: " << myTM.tm_hour << std::endl;
    std::cout << "tm_mday: " << myTM.tm_mday << std::endl;
    std::cout << "tm_mon: " << myTM.tm_mon << std::endl;
    std::cout << "tm_year: " << myTM.tm_year << std::endl;
    std::cout << "tm_wday: " << myTM.tm_wday << std::endl;
    std::cout << "tm_yday: " << myTM.tm_yday << std::endl;
    std::cout << "tm_isdst: " << myTM.tm_isdst << std::endl;
}

bool equalTMs(tm& tm1, tm& tm2)
{
    return (tm1.tm_sec == tm2.tm_sec)
        && (tm1.tm_min == tm2.tm_min)
        && (tm1.tm_hour == tm2.tm_hour)
        && (tm1.tm_mday == tm2.tm_mday)
        && (tm1.tm_mon == tm2.tm_mon)
        && (tm1.tm_year == tm2.tm_year)
        && (tm1.tm_wday == tm2.tm_wday)
        && (tm1.tm_yday == tm2.tm_yday)
        && (tm1.tm_isdst == tm2.tm_isdst);
}

answered question

1 Answer

9

You are calling gmtime_s() to get a tm that is expressed in UTC time, then you pass that to mktime(), which expects the tm to be expressed in LOCAL time instead of UTC time. Use localtime_s() instead of gmtime_s().

posted this

Have an answer?

JD

Please login first before posting an answer.