Strange behaviour in SetSystemTime kernel32
Asked Answered
D

1

2

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?

Dressingdown answered 7/8, 2014 at 9:10 Comment(9)
It's your own code that's causing weirdness with that incHour usage - why do you not properly convert the entire date to UTC and then just use it? Also, not all time zones are at whole hour offsets from UTC, so if this is meant to be portable code, it's broken.Ent
What is the purpose of this code? Is what you want to do equivalent to disabling "Automatically adjust clock for Daylight Saving Time"?Coffle
Damien, I get the whole hour offsets thing and converting the date to UTC but it doesn't explain why the code corked at 13:00 and not at 04:15. The math is virtually the same isn't it? or is there something i'm missing?Dressingdown
Andrew, no, its to sync the pc clock with a server based upon data received over a custom protocol. The PC clock should still adhere to daylight saving.Dressingdown
@Dressingdown It might help if you put UTC and BST on the times you're writing. I can see it going wrong when the hour is 23 and you add 1. Maybe you could use SetLocalTime, the remarks of which have an interesting point about having to call it twice.Coffle
@Andew. Interestingly, the code above should always get the time wrong unless we're in GMT but it doesn't. I'll change it to what I think is correct. i.e. Not adding -1??? to the hour.Dressingdown
@Andrew. I ended up using SetLocalTime per your suggestion. Can't mark your comment as an answer unless you answer it.Dressingdown
@Dressingdown I've made it into an answer for you. Glad it worked.Coffle
SetSystemTime requires UTC, not local time. The Brits always have more trouble with time, having Greenwich so close isn't an advantage :)Biancabiancha
C
2

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.

Coffle answered 7/8, 2014 at 13:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.