Столкнулся с такой проблемой. После отмены перехода на зимнее время функция _mktime64() стала не правильно расчитывать __time64_t для дат зимнего времени прошлых лет. Она считает так, как будто бы раньше тоже не было перехода зимнее/летнее. Для примера возьмём дату "26 Jan 2011 03:00:00" (строка "Зима начала 2011 года" в таблице на странице
http://habrahabr.ru/blogs/sysadm/130363/). Результат должен быть 1296000000. Такой результат даёт функция MySQL UNIX_TIMESTAMP('2011-01-26 03:00:00'). А _mktime64() возвращает 1295996400 (на 1 час меньше).
Если заглянуть внутрь _mktime64()
/*
* Adjust for timezone. No need to check for overflow since
* localtime() will check its arg value
*/
__tzset();
_ERRCHECK(_get_dstbias(&dstbias));
_ERRCHECK(_get_timezone(&timezone));
tmptm1 += timezone;
/*
* Convert this second count back into a time block structure.
* If localtime returns NULL, return an error.
*/
if ( _localtime64_s(&tbtemp, &tmptm1) != 0 )
goto err_mktime;
/*
* Now must compensate for DST. The ANSI rules are to use the
* passed-in tm_isdst flag if it is non-negative. Otherwise,
* compute if DST applies. Recall that tbtemp has the time without
* DST compensation, but has set tm_isdst correctly.
*/
if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) &&
(tbtemp.tm_isdst > 0)) ) {
tmptm1 += dstbias;
if ( _localtime64_s(&tbtemp, &tmptm1) != 0 )
goto err_mktime;
}
то видим, что функциями _get_dstbias(&dstbias) и _get_timezone(&timezone) запрашиваются сдвижки DST и часового пояса действующие на сегодняшний момент. Т.е. dstbias=0 т.к. нет переходов зимнего/летнего времени и timezone=14400 (UTC+4). А ведь на момент "26 Jan 2011 03:00:00" часовой пояс был UTC+3.
Мне просто необходимо что бы _mktime64() в клиентской программе и UNIX_TIMESTAMP(), FROM_UNIXTIME() на MySQL сервере давали одинаковый результат.
Похоже придётся хранить все даты перевода часов с 1970 по 2011 и самому корректировать результат. Хотя оставляю надежду на какой-нибудь дельный совет.