_mktime64() и отмена зимнего времени
От: igyrus  
Дата: 03.12.11 20:59
Оценка: 31 (1) +1
Столкнулся с такой проблемой. После отмены перехода на зимнее время функция _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 и самому корректировать результат. Хотя оставляю надежду на какой-нибудь дельный совет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.