Как преобразовать дату и время utc между любыми часовыми поясами с помощью Windows API?

#windows #datetime #timezone

#Windows #дата и время #Часовой пояс

Вопрос:

Мы ищем способы преобразования даты и времени utc между часовыми поясами (в обоих направлениях) с помощью Windows API, т.е. С Использованием данных часового пояса Windows, поддерживаемых Microsoft.

Возможно ли это?

SystemTimeToTzSpecificLocalTimeEx и TzSpecificLocalTimeToSystemTimeEx, похоже, соответствуют всем требованиям, однако для обоих требуется правильная DYNAMIC_TIME_ZONE_INFORMATION, которая перемещает цель к получению правильной структуры DYNAMIC_TIME_ZONE_INFORMATION.

GetTimeZoneInformation и GetDynamicTimeZoneInformation предоставляют только текущий часовой пояс.

GetTimeZoneInformationForYear (который потребуется для преобразования прошлых дат и времени) требует динамического часового пояса в качестве входных данных.

Как вы можете получить действительную информационную структуру часового пояса для другого часового пояса?

Информация находится в реестре, но как двоичный файл поля TZI, есть ли спецификация о том, как это поле TZI декодируется в TIME_ZONE_INFORMATION ?

Существует enumdynamictimezoneинформация от Win2012 и выше, но мы не можем полагаться на нее, поскольку нам необходимо поддерживать Win2008R2…

PS: использование TZDB для наших нужд проблематично, поскольку мы будем нести ответственность за его обновление в полевых условиях. Ключевым аспектом этого вопроса является то, что нам нужен способ преобразования между TZ без необходимости самостоятельно поддерживать и развертывать информацию о TZ, учитывая, что это может измениться очень быстро.

Комментарии:

1. WRT ваш PS, вы понимаете, что обновление Windows для этого конкретного сценария отставало на 6 недель от обновления TZDB, верно? Смотрите мой блог по этой теме . ИМХО, вам всегда лучше сохранять контроль над своими собственными обновлениями TZ.

2. @Matt, да, я делаю, но если TZDB поддерживается MS, то вина и бремя ложатся на MS (и Египет). Если он поддерживается нами, вина и бремя ложатся на нас (и ИТ-специалистов у клиентов). И не похоже, что мы сможем монетизировать это дополнительное бремя, поэтому поддержание TZDB самостоятельно ставит нас в пресловутую ситуацию проигрыша…

3. Я вас слышу. Хотя, ИМХО, вам лучше иметь возможность обновлять, когда вам нужно, а затем ждать других. Я полагаю, это зависит от того, насколько важны обновления TZ для конкретного приложения. Кроме того, действительно возможно написать код для самостоятельного обновления локальных данных TZDB с каждым выпуском IANA. Я не делал этого на C , но я сделал это на C # с Noda Time, и я знаю по крайней мере одного человека, который сделал это в Elixr.

4. На самом деле, похоже, что библиотека даты Говарда Хиннанта для C имеет AUTO_DOWNLOAD функцию. Я сам не пробовал, но, похоже, он соответствует выпускам TZDB от IANA. Подробнее здесь . Не уверен, обновляется ли он только во время компиляции или также во время выполнения.

5. Мы развернуты на сотнях промышленных объектов, обычно на машинах, которые не имеют доступа к Интернету (или имеют брандмауэр), автоматическое обновление просто невозможно. Простое уведомление всех администраторов о необходимости обновления уже стало бы сложным процессом между внешними администраторами, подрядчиками, корпоративными политиками обновлений, процессами проверки, а также рисками в случае, если обновление tzdb окажется прослушиваемым… И, как уже было сказано, все это не окупится, так что это чистый риск и бремя, которое у нас нет стимула брать на себя…

Ответ №1:

Перечисление реестра, по-видимому, является единственным способом, структура поля TZI описана в https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481 (v = против 85).aspx и выглядит следующим образом

 typedef struct _REG_TZI_FORMAT
{
    LONG Bias;
    LONG StandardBias;
    LONG DaylightBias;
    SYSTEMTIME StandardDate;
    SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;
  

Комментарии:

1. Поскольку вы не можете использовать EnumDynamicTimeZoneInformation из-за необходимости поддержки Win2008R2, я согласен, что вам нужно будет самостоятельно заполнить записи из реестра.