1 year ago

#374946

test-img

PKallback

Conversion of Local Time to GMT/UTC, and back GMT/UTC to Local Time in C++

The problem of conversion from GMT/UTC to local time in C++ is tricky because of daylight saving. To solve the daylight saving problem there must be a table for every country and zone, since daylight saving is not universal. This problem/solution is maybe not universal since I'm still using MFC when coding C++ in Windows.

What I have tried so far is the following... Going from local time to GMT/UTC is quite easy with this example:

void GetGMTTime(int year, int month, int day, int hour, int min, int sec, tm& gmt) {
    CTime date_time(year, month, day, hour, min, sec);

    tm local;
    // This is only for comparison and should be equal to the input variables 
    date_time.GetLocalTm(&local);
    // Conversion to GMT/UTC
    date_time.GetGmtTm(&gmt);       
}

To go the other way arround is more tricky and CTime has no implementation for it. One method is to have a new CTime variable with the GMT/UTC time as the initial value. When running the function CTime::GetGmtTm() will now generate a time that is less than or greater than the GMT/UTC time (well, if you live in UK you don't have this problem). The CTime can than be incremented or decremented by 1 hour until CTime::GetGmtTm() will return the same value as the original GMT/UTC time. To get the local time, run CTime::GetLocalTm() again.

The algorithm above is exemplified with the code below:

void CDateTimeDlg::ConvertTimeFromGMTtoLocal(const tm gmt, tm& local) {
    // Initialization
    CTime test(gmt.tm_year + 1900, gmt.tm_mon + 1, gmt.tm_mday, gmt.tm_hour, gmt.tm_min, gmt.tm_sec);
    tm gmtcmp; // As in GMT compare
    test.GetGmtTm(&gmtcmp);

    while (ConvertTmToUINT(gmt) != ConvertTmToUINT(gmtcmp)) {
        if (ConvertTmToUINT(gmtcmp) < ConvertTmToUINT(gmt)) {
            test += CTimeSpan(0, 1, 0, 0);
        }
        else if (ConvertTmToUINT(gmtcmp) > ConvertTmToUINT(gmt)) {
            test -= CTimeSpan(0, 1, 0, 0);
        }
        test.GetGmtTm(&gmtcmp);
    }

    test.GetLocalTm(&local);
}

// UINT as 32 bit
UINT CDateTimeDlg::ConvertTmToUINT(const tm t) {    
    UINT year = t.tm_year + 1900;
    UINT month = t.tm_mon + 1;
    UINT day = t.tm_mday;
    UINT hour = t.tm_hour;
    UINT min = t.tm_min;
    UINT sec = t.tm_sec;
    UINT days = t.tm_yday;

    UINT uintdate{ 0 };

    uintdate = (year - 1980) << 26;
    uintdate |= days << 17;
    uintdate |= hour << 12;
    uintdate |= min << 6;
    uintdate |= sec;

    return uintdate;
}

My question is if this can be done more easily without using an iteration?

c++

mfc

ctime

0 Answers

Your Answer

Accepted video resources