Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ time_t problem

I'm having trouble with dates management in C++ (VS 2008).

According to MSDN specifications, time_t represents:

The number of seconds since January 1, 1970, 0:00 UTC

therefore, I've written this piece of code:

#include <stdio.h>
#include <time.h>

time_t GetDate(int year, int month, int day, int hour, int min, int sec)
{
    time_t rawtime;
    struct tm * timeinfo;
    
    time ( &rawtime );
    timeinfo = gmtime ( &rawtime );
    timeinfo->tm_year = year - 1900;
    timeinfo->tm_mon = month - 1;
    timeinfo->tm_mday = day;
    timeinfo->tm_hour = hour;
    timeinfo->tm_min = min;
    timeinfo->tm_sec = sec;
    timeinfo->tm_isdst = 0; // disable daylight saving time
    
    time_t ret = mktime ( timeinfo );
    
    return ret;
}

int main ()
{
    time_t time_0 = GetDate(1970,1,1,0,0,0);
    // time_0 == -1 !!!
    time_t time_1 = GetDate(1970,1,1,1,0,0);
    // time_1 == 0 !!!
    return 0;
}

It seems to be shifted by 1 hour (i.e. zero time is January 1, 1970, 1:00 UTC).

Initially, I thought the problem could come from the DayLightSaving flag, but it doesn't change by changing it.

Am I doing something wrong ?

Thanks in advance


P.S. In theory, I might not mind the zero time value, because it's only a reference time.

But I need to be sure about the value, because I'm porting the code to another language and I need to get exactly the same results.


EDIT:

here's the solution, thanks to Josh Kelley Answer

time_t mktimeUTC(struct tm* timeinfo)
{
    // *** enter in UTC mode
    char* oldTZ = getenv("TZ");
    putenv("TZ=UTC");
    _tzset();
    // ***

    time_t ret = mktime ( timeinfo );

    // *** Restore previous TZ
    if(oldTZ == NULL)
    {
        putenv("TZ=");
    }
    else
    {
        char buff[255];
        sprintf(buff,"TZ=%s",oldTZ);
        putenv(buff);
    }
    _tzset();
    // ***

    return ret;
}
like image 261
digEmAll Avatar asked Sep 07 '10 17:09

digEmAll


2 Answers

mktime takes a struct tm giving a local time and returns the number of seconds since January 1, 1970, 0:00 UTC. Therefore, your GetDate(1970,1,1,0,0,0); call will return 0 if your local time zone is UTC but may return other values for other time zones.

Edit: For a UTC version of mktime or your GetDate, try the following (untested):

  1. Call getenv to save the current value of the TZ environment variable (if any).
  2. Call putenv to change the TZ environment variable to "UTC".
  3. Call _tzset to make your changes active.
  4. Call mktime.
  5. Restore the old value of TZ, then call _tzset again.
like image 97
Josh Kelley Avatar answered Nov 18 '22 02:11

Josh Kelley


Just a WAG but try the following:

timeinfo->tm_year = year - (unsigned long)1900;
timeinfo->tm_mon = month - (unsigned long)1;
like image 21
Hogan Avatar answered Nov 18 '22 02:11

Hogan