3

I have a call to SetSystemTime from my c# application. However if I have the Windows timezone set to a non-zero offset from UTC, it seems sometimes to adjust the system clock as if the time I provided was UTC (i.e. converts to local time) and other times it doesn't, it just sets the time directly to the date parameter.

    [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);
    }

The difference seems to be: When I set the time zone using Windows, then start the application, when I call SetSystemTime() it adjusts the time provided as if it was UTC.

But when I set the time zone using the SetDynamicTimeZoneInformation() function, restart the application and then call SetSystemTime() then it sets the time directly to the time I provide, regardless of the time zone.

Is this the expected behaviour? How can I get consistency between the two methods for setting the time zone?

komodosp
  • 3,316
  • 2
  • 30
  • 59
  • SetSystemTime() almost never "sets the time directly to the time I provide". It sets the UTC time. Except when you live in Ireland, located in the UTC+0 timezone. Not exactly a blessing. Randomly calling SetDynamicTimeZoneInformation() is not generally sensible unless the computer is located in an airplane :) Making a .NET program aware of a timezone changes requires restarting it (like you did) or calling CultureInfo.ClearCachedData + TimeZoneInfo.ClearCachedData. Don't do this. – Hans Passant Mar 22 '17 at 13:25
  • Windows computers sync their time automatically. Wouldn't it be safer to use the built-in functionality? You can change the sync frequency or force a sync [through settings and the Win32tm tool](https://technet.microsoft.com/en-us/windows-server-docs/identity/ad-ds/get-started/windows-time-service/windows-time-service-tools-and-settings) – Panagiotis Kanavos Mar 22 '17 at 14:33

1 Answers1

1

I believe I found the problem.

It turns out the person who wrote the bit of code to SetDynamicTimeZoneInformation() neglected to set the Bias property.

Therefore the timezone information being set had a UTC offset of zero, so no adjustment would take place.

komodosp
  • 3,316
  • 2
  • 30
  • 59
  • Instead of setting the time yourself, why don't you let the OS do it automatically? Domain computers automatically sync with the domain controller. Standalone computers (or DCs) sync automatically with the time servers specified in Date & Time settings – Panagiotis Kanavos Mar 22 '17 at 14:30
  • @PanagiotisKanavos - I wasn't the original developer on the application, but they apparently had good reason for doing it this way. For one thing, it's on a specialised device (Windows Embedded 7) which doesn't provide user access to the main Windows OS. (A shell application loads this application when they turn on the device and then turns off the device when they quit the app) – komodosp Mar 22 '17 at 16:10
  • Time synchronization is available on Windows Embedded as well . Check this SO question: [Setting internet time server on windows embedded standard through batch or similar](http://stackoverflow.com/questions/34016933/setting-internet-time-server-on-windows-embedded-standard-through-batch-or-simil). Without synchronized clocks you can't use SSL or any other form of encryption that checks for expired packets. That includes communication with domain controlelrs. – Panagiotis Kanavos Mar 22 '17 at 16:16
  • @colmde can you post your whole solution? – BNT Jan 18 '18 at 10:48
  • 1
    @BNT - apologies, I'm not sure I have access to the same code now, but I'll have a look, but to explain, when the application set the time zone in the first place, there was a call to `SetDynamicTimeZoneInformation()` which has a parameter which is a `DYNAMIC_TIME_ZONE_INFORMATION` struct - this has properties such as `Bias`, which is the number of minutes offset from UTC and `StandardBias` and `DaylightBias`. These need to be set correctly when making the call - hope this helps. See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724932(v=vs.85).aspx – komodosp Jan 18 '18 at 11:17