TimeZoneInfo.ConvertTimeFromUtc неправильно применяет DST к развернутой веб-работе Azure - PullRequest
2 голосов
/ 17 апреля 2019

У нас есть веб-задание, которое работает на .Net Framework 4.7.1 и выполняет преобразование даты и времени из DateTimeOffset.UtcNow в континентальное время Чили (то есть, если я не ошибаюсь, "Стандартное время Pacific SA").

При локальном запуске этого веб-задания (на компьютере с Windows 10) он работает правильно и выполняет преобразование с применением DST, но при развертывании в службе приложений Azure это больше не работает, а окончательный DateTime всегда через час чем текущее официальное время.

Я изначально переключился с TimeZoneInfo.ConvertTimeBySystemTimeZoneId на TimeZoneInfo.ConvertTimeFromUtc в предположении, что первый не учитывает DST, но это не сработало;

Затем я попытался переключить «неправильный» собственный компьютер, изменив часовой пояс на «UTC_dstoff» и отключив в меню «Настройка даты / времени» параметры «Автоматически настраивать летнее время», а также «Автоматически устанавливать время». 'но все еще работает, как и ожидалось, локально;

Последнее, что я пытался, это изменить часовой пояс на службу приложений, используя переменную среды WEBSITE_TIME_ZONE на «Pacific SA Standard Time», и это не было убедительным. Я бы сказал, что первоначально это сработало, но после еще нескольких изменений часового пояса он снова начал прибавлять один час.

Это можно воспроизвести следующими строками:

var timeZoneId = "Pacific SA Standard Time";
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
var dateTimeOffset = DateTimeOffset.UtcNow;

var localTime = TimeZoneInfo.ConvertTimeFromUtc(dateTimeOffset.DateTime, timeZone);

Я ожидаю, что функция TimeZoneInfo.ConvertTimeFromUtc будет правильно применять DST, когда часовой пояс с DST будет выбран как локально, так и в службе приложений Azure. Вместо этого он, кажется, работает должным образом в Windows 10, но случайным образом в службе приложений Azure.

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Обновление

Может показаться, что обновление часового пояса в KB4486459 , которое охватывало изменения для расписания перехода на летнее время в Чили в 2019 , еще не применялось к службе приложений Azure. Таким образом объясняется, почему вы получили разные результаты локально для определенных дат, чем при развертывании в Azure.

4486459 входит в исправления гостевой ОС Azure за март 2019 года , которые все еще развертываются в службе приложений Azure. Таким образом, эта проблема разрешится сама собой, когда отдельные экземпляры получат обновления.


Оригинальный ответ

Несколько вещей:

  • WEBSITE_TIME_ZONE следует использовать только в том случае, если у вас есть код, который вы не можете изменить, который работает по местному времени. Например, если у вас много звонков на DateTime.Now, это будет отражать местный часовой пояс. Изменение WEBSITE_TIME_ZONE изменит часовой пояс, используемый для определения этого. Если у вас есть контроль над собственным кодом, просто никогда не пишите DateTime.Now или используйте любую другую функцию, которая зависит от местного часового пояса. Тогда вам никогда не понадобится использовать эту настройку. Считайте это последним средством, а не рекомендуемым способом ведения дел.

  • В общем, вы должны стараться не писать код на стороне сервера, который изменит свое поведение в зависимости от настроек часового пояса системы, будь то код на панели управления на вашем локальном компьютере или параметр WEBSITE_TIME_ZONE упомянутый выше.

  • Не то чтобы это имело значение, но настройку «Настроить для летнего времени автоматически» почти всегда следует оставлять включенной. Отключение (или передача _dstoff в TZUtil.exe) в основном является устаревшим параметром. (Есть редкий крайний случай, но об этом не стоит говорить.)

  • Да, "Pacific SA Standard Time" - правильный идентификатор часового пояса Windows для материковой части Чили (Сантьяго). Другие, которые относятся к Чили, относятся к Пунта-Аренасу ("Magallanes Standard Time") и острову Пасхи ("Easter Island Standard Time").

  • Имейте в виду, что в Чили в 2019 году было изменено число дат перехода на летнее время. Прочтите об этом здесь . Это было выпущено в обновлении Microsoft в феврале 2019 года, описано здесь . Это обновление уже должно быть установлено на вашем веб-сайте Azure, но вы можете проверить свой собственный локальный компьютер.

  • Вы сказали, что изначально использовали TimeZoneInfo.ConvertTimeBySystemTimeZoneId. Если вы использовали перегрузку, которая принимает DateTime, помните, что если .Kind равно DateTimeKind.Unspecified, то оно будет обрабатываться как местное время. Если вы не изменили WEBSITE_TIME_ZONE, то по умолчанию местное время равно UTC. Но если вы это сделаете, то это повлияет на поведение.

  • Также учтите, что когда вы запрашиваете .DateTime свойство DateTimeOffset, тип всегда будет DateTimeKind.Unspecified. Хотя это не влияет на ваш текущий код, потому что TimeZoneInfo.ConvertTimeFromUtc обрабатывает неопределенный вид, как если бы это был UTC (отсюда и название "FromUTC").

  • Если вы работаете с типами DateTimeOffset, вам лучше использовать TimeZoneInfo.ConvertTimeBySystemTimeZoneId или просто TimeZoneInfo.ConvertTime с перегрузками, которые принимают и возвращают DateTimeOffset. Тогда DateTimeKind не встанет у вас на пути.

Наконец, я укажу, что ваш вопрос не очень ясен в отношении того, что не работает точно. Код, который вы показали, в конечном итоге будет работать правильно, даже если он не идеален. В нем нет ничего, что могло бы давать прерывистые результаты, независимо от того, изменили ли вы системные настройки или WEBSITE_TIME_ZONE. Возможно ли, что вы просто кормите в разные даты и время и видите, что у некоторых есть летнее время, а у других нет? Если это так, это может быть совершенно нормально. Я бы сравнил их с графиком Чили по летнему времени , чтобы узнать, совпадают они или нет. Помните, дело не в том, применяется ли DST во время выполнения вашего кода или нет, а в том, применяется ли оно для значения, данного .

Если вы все еще видите проблемы, пожалуйста, прокомментируйте пример ввода и вывода вместе с тем, что вы ожидали. Спасибо.

1 голос
/ 18 апреля 2019

В Azure добавьте WEBSITE_TIME_ZONE к Pacific SA Standard Time и используйте методы структуры TimeZoneInfo , как показано ниже:

DateTime timeUtc = DateTime.UtcNow;
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time"); 
DateTime kstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, timeZone );
...