Confusing behaviour of mktime() function : increasing tm_hour count by one

Wow, there just is no way around it. It must be a bug in your system's implementation of mktime(3). mktime(3) should not alter the struct tm * passed to it.

I would suggest checking the value of storage.tm_isdst. Try setting it to 0 to ensure it's not confused about DST. If that doesn't work, try setting it to -1 to let it auto determine the proper value.

mktime - convert broken-down time into time since the Epoch

A positive or 0 value for tm_isdst causes mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A negative value for tm_isdst causes mktime() to attempt to determine whether Daylight Saving Time is in effect for the specified time.


I was wrong about mktime(3) not modifying struct tm *. It is the correct behavior to normalize the value.


What happens

The date you specified has daylight savings in effect but when calling mktime, storage.tm_isdst is zero. mktime sees this and thinks "hey, they gave me a date with an incorrect daylight savings flag, lets fix it". Then it sets tm_isdst to 1 and changes tm_hour.

See also this answer.

To fix it

  • use timegm instead of mktime
  • set the timezone to UTC before calling mktime (see also example from timegm) :
    setenv("TZ", "", 1);
    tzset();
    mktime();
  • use a good date-time library (like boost::locale::date_time/boost::date_time, but read the Q&A section on the boost::locale::date_time page before picking one)

Tags:

C++

Dst

Mktime