SetSystemTime - UTC или местное время?

У меня есть вызов SetSystemTime из моего приложения С#. Однако, если у меня установлен часовой пояс Windows с ненулевым смещением от UTC, иногда кажется, что системные часы настраиваются так, как если бы предоставленное мной время было UTC (т.е. преобразовывалось в местное время), а в других случаях это не так, это просто устанавливает время непосредственно в параметр date.

    [StructLayout(LayoutKind.Sequential)]
    internal struct SystemTime
    {
        public short Year;
        public short Month;
        public short DayOfWeek;
        public short Day;
        public short Hour;
        public short Minute;
        public short Second;
        public short Milliseconds;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool SetSystemTime(ref SystemTime st);

    public static bool AdjustSystemClock(DateTime date)
    {
        SystemTime systemTime = new SystemTime();
        systemTime.Year = (short)date.Year;
        systemTime.Month = (short)date.Month;
        systemTime.Day = (short)date.Day;
        systemTime.Hour = (short)date.Hour;
        systemTime.Minute = (short)date.Minute;
        systemTime.Second = (short)date.Second;
        return SetSystemTime(ref systemTime);
    }

Разница, кажется, заключается в следующем: когда я устанавливаю часовой пояс с помощью Windows, затем запускаю приложение, когда я вызываю SetSystemTime(), оно настраивает предоставленное время, как если бы это было UTC.

Но когда я устанавливаю часовой пояс с помощью функции SetDynamicTimeZoneInformation(), перезапускаю приложение, а затем вызываю SetSystemTime(), тогда оно устанавливает время непосредственно на время, которое я предоставляю, независимо от часового пояса.

Это ожидаемое поведение? Как я могу добиться согласованности между двумя методами установки часового пояса?


person colmde    schedule 22.03.2017    source источник
comment
SetSystemTime() почти никогда не устанавливает время непосредственно в то время, которое я указываю. Он устанавливает время UTC. За исключением случаев, когда вы живете в Ирландии, расположенной в часовом поясе UTC+0. Не совсем благословение. Случайный вызов SetDynamicTimeZoneInformation() обычно не имеет смысла, если только компьютер не находится в самолете :) Чтобы программа .NET узнала об изменениях часового пояса, необходимо перезапустить ее (как вы это сделали) или вызвать CultureInfo.ClearCachedData + TimeZoneInfo.ClearCachedData. Не делай этого.   -  person Hans Passant    schedule 22.03.2017
comment
Компьютеры Windows синхронизируют свое время автоматически. Не безопаснее ли использовать встроенный функционал? Вы можете изменить частоту синхронизации или принудительно выполнить синхронизацию через настройки и инструмент Win32tm   -  person Panagiotis Kanavos    schedule 22.03.2017


Ответы (1)


Я считаю, что нашел проблему.

Оказывается, человек, написавший часть кода для SetDynamicTimeZoneInformation(), забыл установить свойство Bias.

Таким образом, устанавливаемая информация о часовом поясе имела смещение UTC, равное нулю, поэтому корректировка не производилась.

person colmde    schedule 22.03.2017
comment
Вместо того, чтобы устанавливать время самостоятельно, почему бы вам не позволить ОС делать это автоматически? Компьютеры домена автоматически синхронизируются с контроллером домена. Автономные компьютеры (или контроллеры домена) автоматически синхронизируются с серверами времени, указанными в настройках даты и времени. - person Panagiotis Kanavos; 22.03.2017
comment
@PanagiotisKanavos - я не был первоначальным разработчиком приложения, но у них, очевидно, были веские причины для этого. Во-первых, он находится на специализированном устройстве (Windows Embedded 7), которое не предоставляет пользователю доступ к основной ОС Windows. (Приложение оболочки загружает это приложение при включении устройства, а затем выключает устройство при выходе из приложения) - person colmde; 22.03.2017
comment
Синхронизация времени также доступна в Windows Embedded. Проверьте этот вопрос SO: Настройка времени в Интернете сервер на Windows Embedded Standard через пакетную или аналогичную. Без синхронизированных часов вы не сможете использовать SSL или любую другую форму шифрования, которая проверяет пакеты с истекшим сроком действия. Это включает в себя связь с контроллерами домена. - person Panagiotis Kanavos; 22.03.2017
comment
@colmde, можете ли вы опубликовать все свое решение? - person BNT; 18.01.2018
comment
@BNT - извините, я не уверен, что сейчас у меня есть доступ к тому же коду, но я посмотрю, но чтобы объяснить, когда приложение установило часовой пояс в первую очередь, был вызов SetDynamicTimeZoneInformation() который имеет параметр, который является структурой DYNAMIC_TIME_ZONE_INFORMATION — у него есть такие свойства, как Bias, который представляет собой количество минут, смещенных от UTC, а также StandardBias и DaylightBias. Их нужно правильно установить при совершении звонка - надеюсь, это поможет. См. msdn.microsoft.com/ en-us/library/windows/desktop/ - person colmde; 18.01.2018