_Mktime64 правильно обрабатывает исторические правила DST? - PullRequest
0 голосов
/ 03 января 2019

Я использую функцию _mktime64 для преобразования местного времени в UTC (на машине с Windows). Входными данными для функции _mktime64 могут быть как прошлые, так и будущие даты. Кажется, что функция всегда использует текущие правила DST, которые действуют во время выполнения, а не какие-либо исторические правила (которые присутствуют в окнах!). Я ищу подтверждение того, что это так.

В США, похоже, правила DST изменились в 2007 году (см., Например, https://en.wikipedia.org/wiki/Eastern_Time_Zone). Поэтому до 2007 года летнее время в восточном часовом поясе начинается в первое воскресенье апреля в 2 часа ночи. В то время как с 2007 года летнее время в восточном часовом поясе начинается во второе воскресенье марта в 2 часа ночи.

Первое воскресенье апреля 2003 года было 6-го, так что это будет день, когда должно начаться летнее время.

Теперь разница во времени между восточным часовым поясом и UTC составляет -5 часов по стандартному времени и -4 часа по летнему времени.

Итак, при преобразовании 1 апреля 2003 года в UTC я ожидаю разницу в 5 часов, так как летнее время еще не началось. При преобразовании 1 апреля 2008 года в UTC я ожидаю разницу в 4 часа, так как летнее время уже началось в этом году.

Однако, похоже, что результат за 1 апреля 2003 года неверен.

Из документа MSDN (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/mktime-mktime32-mktime64?view=vs-2017)) я могу прочитать, что он пытается определить информацию о летнем времени из переменной TZ env. Или через функцию GetTimeZoneInformation. У меня нет переменной TZ env, поэтому я предполагаю, что она использует функцию GetTimeZoneInformation. Документ (https://docs.microsoft.com/en-us/windows/desktop/api/timezoneapi/nf-timezoneapi-gettimezoneinformation) для этой функции, похоже, упоминает, что она возвращает «текущие настройки часового пояса»). Здесь мне становится немного неясно. Должен ли я интерпретировать это как текущие правила DST? Или все правила часового пояса, который сейчас настроен на моей машине? Кажется, это означает «текущие правила перехода на летнее время», но я хотел бы получить подтверждение.

#include <iostream>

#include <time.h>

int main()
   {
   std::tm tmStruct;
   std::tm *tmStructPtr;
   __time64_t res;

   // running on a machine in Eastern Time Zone

   std::cout << std::endl << "april 1 2003 00:00:00" << std::endl;
   tmStruct.tm_mday = 1;
   tmStruct.tm_mon = 3;  // april
   tmStruct.tm_year = 103; // 2003
   tmStruct.tm_hour = 0;
   tmStruct.tm_min = 0;
   tmStruct.tm_sec = 0;
   tmStruct.tm_isdst = -1;  // don't know, figure it out yourself
   res = _mktime64(&tmStruct);
   std::cout << res << std::endl;
   tmStructPtr = _gmtime64(&res);
   std::cout << tmStructPtr->tm_hour << std::endl;   // prints out 4 while DST should not have started yet!

   std::cout << std::endl << "april 1 2008 00:00:00" << std::endl;
   tmStruct.tm_mday = 1;
   tmStruct.tm_mon = 3;  // april
   tmStruct.tm_year = 108; // 2008
   tmStruct.tm_hour = 0;
   tmStruct.tm_min = 0;
   tmStruct.tm_sec = 0;
   tmStruct.tm_isdst = -1;  // don't know, figure it out yourself
   res = _mktime64(&tmStruct);
   std::cout << res << std::endl;
   tmStructPtr = _gmtime64(&res);
   std::cout << tmStructPtr->tm_hour << std::endl;   // prints out 4 = ok
   return 0;
   }
...