mktime shifts a time by one hour

1.1k views Asked by At

I faced with an interesting problem with mktime function. I use russian time zone (UTC+03:00) Волгоград, Москва, Санкт-Петербург (RTZ 2) / Volgograd, Moscow, Saint Petersburg/ and try to construct time_t for "7.01.2009 00:00:00"

tm localTM;

localTM.tm_sec = 0;
localTM.tm_min = 0;
localTM.tm_hour = 0;
localTM.tm_mday = 7;
localTM.tm_mon = 0;
localTM.tm_year = 109;

time_t t = mktime(&localTM);

After mktime execution date&time is changed to "6.01.2009 23:00:00".

I have no problems then I construct time for "06.01.2009 00:00:00" or "08.01.2009 00:00:00". If I switch time zone to another one, I get no problems with "7.01.2009 00:00:00".

What can be a reason of this oddity, and how can I workaround the issue?

1

There are 1 answers

0
Marcin Zukowski On

When performing conversion to time_t, mktime needs to guess if the input is DST (Daylight Saving Time) or not. For that, tm.tm_isdst field is used. See from man mktime

   tm_isdst  A  flag  that  indicates  whether  daylight saving time is in
             effect at the time described.  The value is positive if  day-
             light  saving time is in effect, zero if it is not, and nega-
             tive if the information is not available.

Since you do not initialize tm_isdst in your code, the default value (0) is used, making mktime think it's in NO-DST period. To fix it in your code, simply add

 localTM.tm_isdst = -1

Note - that logic is necessary as for some moments in time just the "wallclock" information stored in tm is not sufficient to determine the exact time.

And yes, the fact that the default behavior is like that is a bit messed up :)