Search code examples
.netvb.netwindowskernel32

Strange behaviour in SetSystemTime kernel32


I have the following code:

Public Class SetSystemTime
    Structure SYSTEMTIME
        Public wYear As Short
        Public wMonth As Short
        Public wDayOfWeek As Short
        Public wDay As Short
        Public wHour As Short
        Public wMinute As Short
        Public wSecond As Short
        Public wMilliseconds As Short
    End Structure

    Public Declare Function SetSystemTime Lib "kernel32" (ByRef lpSystemTime As SYSTEMTIME) As Boolean
End Class

Private Sub SetDateTime(dt As DateTime)
    Dim dateTimeStruct As SetSystemTime.SYSTEMTIME
    Dim incHour As Integer = DateDiff(DateInterval.Hour, Now, Date.UtcNow)

    With dateTimeStruct
        .wDay = dt.Day
        .wDayOfWeek = dt.DayOfWeek
        .wHour = dt.Hour + incHour
        .wMilliseconds = dt.Millisecond
        .wMinute = dt.Minute
        .wMonth = dt.Month
        .wSecond = dt.Second
        .wYear = dt.Year
    End With

    SetSystemTime.SetSystemTime(dateTimeStruct)
End Sub

The behaviour I have seen is that at 2014-08-04 04:15:07, the method SetDateTime above was executed with dt as 04/08/2014 04:15:07 so effectively, the time was set but in reality, hadn't changed. My logs show me that the PC clock jumped to 2014-08-04 05:15:07 as a result of the change. Subsequently, at 2014-08-04 13:00:28 (14:00:28 PC time), the method was called again and the clock was set back to 2014-08-04 13:00:28

What could possibly cause this behaviour. Timezone is set to London and we're currently in daylight saving until October. The OS is Win7 Embedded Standard.

Any ideas?


Solution

  • Use the SetLocalTime function instead, and please take careful note of the remark in its documentation:

    The system uses UTC internally. Therefore, when you call SetLocalTime, the system uses the current time zone information to perform the conversion, including the daylight saving time setting. Note that the system uses the daylight saving time setting of the current time, not the new time you are setting. Therefore, to ensure the correct result, call SetLocalTime a second time, now that the first call has updated the daylight saving time setting.