Reputation: 163
I just noticed using coredll (Win CE) function [SetSystemTime
][1] to set the datetime it updates the time then daylight saving is evaluated.
For example: Today is 5/9/2014 and the time is 11:00am local. So the CE device's app says my current date is 1/1/2014 time xx:xx and then ask what date and time do you want? We say 5/9/2014 11:00am
The current date is NOT DST and the new date is, using the .NET [ToUniversalTime
][2] function we convert to UTC (5/9/2014 4:00pm). It considers the new datetime is in DST and considers it in the conversion. So we set our [SYSTEMTIME
][3] structure to:
Dim utc As DateTime = #5/9/2014 11:00am#.ToUniversalTime()
Dim st As New SYSTEMTIME
st.Year = CUShort(utc.Year)
st.Month = CUShort(utc.Month)
st.Day = CUShort(utc.Day)
st.Hour = CUShort(utc.Hour)
st.Minute = CUShort(utc.Minute)
st.Second = CUShort(utc.Second)
st.Milliseconds = CUShort(utc.Millisecond)
You think I just set the time to 5/9/2014 11:00am, but no it is 10:00am.
Here is my guess of what is happening. The date and time is set then Windows says "oh today is now a DST, I need to adjust the time" and now you are an hour off of what you expected. It does not matter if you are going to or from DST. Run the same function a second time and you get the expected results because now windows does not have to adjust for a transition into or out of DST.
For now my only workaround I can think of is setting a flag before the change
Dim DSTTranstions As Boolean = _
Not (TimeZone.CurrentTimeZone.IsDaylightSavingTime(Now) = _
TimeZone.CurrentTimeZone.IsDaylightSavingTime(newTime))
If the flag is set, then call it a second time
Am I making this too hard?
Also, I have not tested this on kernel32 ("desktop windows"), I am guessing it would be the same logic.
Here is the entire code:
<DllImport("coredll.dll"), CLSCompliant(False)> _
Public Function SetSystemTime(ByRef lpSystemTime As SYSTEMTIME) As UInt32
End Function
<StructLayout(LayoutKind.Sequential), CLSCompliant(False)> _
Public Structure SYSTEMTIME
Dim Year As UInt16
Dim Month As UInt16
Dim DayOfWeek As UInt16
Dim Day As UInt16
Dim Hour As UInt16
Dim Minute As UInt16
Dim Second As UInt16
Dim Milliseconds As UInt16
End Structure
Public Function SetTime(ByVal newTime As Date, _
Optional ByVal DateIsUTC As Boolean = False) As Boolean
Try
Dim utc As Date = Nothing
If DateIsUTC Then
utc = newTime
Else
utc = newTime.ToUniversalTime()
End If
Dim DSTTranstions As Boolean = Not (TimeZone.CurrentTimeZone.IsDaylightSavingTime(Now) = _
TimeZone.CurrentTimeZone.IsDaylightSavingTime(newTime))
If DSTTranstions AndAlso TimeZone.CurrentTimeZone.IsDaylightSavingTime(Now) Then
utc = utc.AddHours(-1)
ElseIf DSTTranstions AndAlso Not TimeZone.CurrentTimeZone.IsDaylightSavingTime(Now) Then
utc = utc.AddHours(1)
End If
Dim st As New SYSTEMTIME
st.Year = CUShort(utc.Year)
st.Month = CUShort(utc.Month)
st.Day = CUShort(utc.Day)
st.Hour = CUShort((utc.Hour))
st.Minute = CUShort((utc.Minute))
st.Second = CUShort((utc.Second))
st.Milliseconds = CUShort(utc.Millisecond)
Return CBool(SetSystemTime(st))
Catch ex As Exception
MyMessages.Show(ex.ToString)
Return False
End Try
End Function
I apologize to everyone, I must not be explaining the issue very well. I think because of the example everyone is hearing me say the issue is a “SetSystemTime”. I believe “SetSystemTime” and “ToUniversalTime” all work as expected. I think it is an effect of the OS.
We all know if the OS is set for update automatic DST, then the clock when DST comes around according to the DST parameters the OS adjust the clock accordingly. I SHOULD HAVE RELAIZED that if I am updating the clock’s date and the old date’s DST is opposite of the new date’s DST after the update the OS will adjust the time to the correct DST time. Hence the test “
Dim DSTTranstions As Boolean = Not (TimeZone.CurrentTimeZone.IsDaylightSavingTime(Now) = _
TimeZone.CurrentTimeZone.IsDaylightSavingTime(newTime))
” DSTTranstions will be true if the old and new date’s DST is opposite of each other. Then the test which way is the DST transitioning either to ON or OFF and pre-adjusts the time accordingly. So when the OS does it adjustment it is as expected.
It just took me awhile to connect the dots. My question was what was the best way to handle this rare scenario. Matt point “See the second paragraph of this answer regarding the device manufacturer's implementation” could also come into play. He is right, the problems are not the same, but what it does tell us is the individual manufactures write their own drivers. For information, I my CE device is a Motorola 9190. I hope this make better sense.
_________________ 7/11/2014 Still not sure whats up. I put my new code into production this week. I will include my new code and log snippet. There is an issue when transitions from DST to not DST. The offset code takes care of that. But I was fixing a time in the same day, so this could not have been a transition. Here what's weird. I have tested it in a 100 locations for the last two weeks. After the first jump, some forward some backward, I have not notice it happening again. The handheld is used to inventory a store. I load a batch into the CE devices using rapi. Then using rapi I execute a program CeSyncTime on the CE device. CeSyncTime takes parameters as date/time then sets the devices date/time. Looking at the log on the pc, it did execute the CeSyncTime at 1:35pm. As you can see from the log snippet, the original time was 7/9/2014 2:35pm. It is setting the time to 7/9/2014 1:35pm. As the CeSyncTime ends it logs the time one last time, the new time is 7/9/2014 12:35pm. I don't think this is the cache issue because when the Brscanner (different application) starts it time is 7/9/2014 12:35pm. When the stores does an inventory the next day the same process. Started at 7/10/2014 1:30pm. The time is going from 12:30pm to 1:30pm and end with the right time of 1:30pm. I just don't see my issue. I am going to ask my motorola rep to have an engineer look at this thread. I will let you guy's know if I hear anything. Frist the code, then the 9th and 11th code snippets.
Public Function SetTime(ByVal newTime As Date, _
Optional ByVal DateIsUTC As Boolean = False) As Boolean
Try
Dim CurrentTime As Date = Now
Dim utc As Date = Nothing
If DateIsUTC Then
utc = newTime
Else
utc = newTime.ToUniversalTime()
End If
Dim DSTTranstions As Boolean = Not (TimeZone.CurrentTimeZone.IsDaylightSavingTime(CurrentTime) = _
TimeZone.CurrentTimeZone.IsDaylightSavingTime(newTime))
Dim DSTTranstionOffset As Integer = 0
If DSTTranstions AndAlso TimeZone.CurrentTimeZone.IsDaylightSavingTime(CurrentTime) Then
DSTTranstionOffset = -1
ElseIf DSTTranstions AndAlso Not TimeZone.CurrentTimeZone.IsDaylightSavingTime(CurrentTime) Then
DSTTranstionOffset = 1
End If
utc = utc.AddHours(DSTTranstionOffset)
Dim st As New SYSTEMTIME
st.Year = CUShort(utc.Year)
st.Month = CUShort(utc.Month)
st.Day = CUShort(utc.Day)
st.Hour = CUShort((utc.Hour))
st.Minute = CUShort((utc.Minute))
st.Second = CUShort((utc.Second))
st.Milliseconds = CUShort(utc.Millisecond)
'Logger.LogCurrentTimeInfo()
'Logger.Log(" SetTime - (UTC) " & utc.ToString)
Logger.Log(" SetTime - Diagnostic Infomation - Start")
Logger.Log(" SetTime - CurrentTime: " & CurrentTime.ToString)
Logger.Log(" SetTime - NewTime: " & newTime.ToString)
Logger.Log(" SetTime - DSTTranstions: " & DSTTranstions.ToString)
Logger.Log(" SetTime - DSTTranstionOffset: " & DSTTranstionOffset.ToString)
Logger.Log(" SetTime - utc: " & utc.ToString)
Logger.Log(" SetTime - st: " & st.Year & ", " & st.Month & ", " & st.Day & " - " & st.Hour & ":" & st.Minute & ":" & st.Second & "." & st.Milliseconds)
Dim SetSystemTimeRetValue As Boolean = CBool(SetSystemTime(st))
Logger.Log(" SetTime - SetSystemTimeRetValue: " & SetSystemTimeRetValue.ToString)
Logger.Log(" SetTime - Diagnostic Infomation - End")
Return SetSystemTimeRetValue
Catch ex As Exception
Logger.Log(" SetTime - Error - " & ex.ToString)
MyMessages.Show(ex.ToString)
Logger.LogError(ex.ToString)
Return False
End Try
End Function
CeSyncTime 7/9/14 2:35:02 PM Starting Set Time (from 7/9/14 2:35:02 PM to 7/9/14 1:35:03 PM) Version: 5.1.0.8 CeSyncTime 7/9/14 2:35:02 PM SetTime - Diagnostic Infomation - Start CeSyncTime 7/9/14 2:35:02 PM SetTime - CurrentTime: 7/9/14 2:35:02 PM CeSyncTime 7/9/14 2:35:02 PM SetTime - NewTime: 7/9/14 1:35:03 PM CeSyncTime 7/9/14 2:35:02 PM SetTime - DSTTranstions: False CeSyncTime 7/9/14 2:35:02 PM SetTime - DSTTranstionOffset: 0 CeSyncTime 7/9/14 2:35:02 PM SetTime - utc: 7/9/14 6:35:03 PM CeSyncTime 7/9/14 2:35:02 PM SetTime - st: 2014, 7, 9 - 18:35:3.0 CeSyncTime 7/9/14 1:35:03 PM SetTime - SetSystemTimeRetValue: True CeSyncTime 7/9/14 1:35:03 PM SetTime - Diagnostic Infomation - End CeSyncTime 7/9/14 12:35:08 PM Program ended! Br Scanner 7/9/14 12:35:31 PM frmMain_Closing - Last power log,disable power notifications, and dispose of scanner. Br Scanner 7/9/14 12:35:31 PM frmMain_Closing - Done Br Scanner 7/9/14 12:35:31 PM Total Loading Time: 167275021 Milliseconds Br Scanner 7/9/14 12:35:31 PM Main Form Done. Br Scanner 7/9/14 12:35:31 PM Disposing Main Form Br Scanner 7/9/14 12:35:31 PM Removing scanner Handler. Br Scanner 7/9/14 12:35:31 PM Disposing Scanner. MDIShell 7/9/14 12:35:32 PM Starting Br Scanner (KeepRunning) Restart Count: 1 Br Scanner 7/9/14 12:35:33 PM Started Br Scanner 7/9/14 12:35:33 PM Version 5.1.0.8
The next day
CeSyncTime 7/10/14 12:30:46 PM Starting Set Time (from 7/10/14 12:30:46 PM to 7/10/14 1:30:46 PM) Version: 5.1.0.8 CeSyncTime 7/10/14 12:30:46 PM SetTime - Diagnostic Infomation - Start CeSyncTime 7/10/14 12:30:46 PM SetTime - CurrentTime: 7/10/14 12:30:46 PM CeSyncTime 7/10/14 12:30:46 PM SetTime - NewTime: 7/10/14 1:30:46 PM CeSyncTime 7/10/14 12:30:46 PM SetTime - DSTTranstions: False CeSyncTime 7/10/14 12:30:46 PM SetTime - DSTTranstionOffset: 0 CeSyncTime 7/10/14 12:30:46 PM SetTime - utc: 7/10/14 6:30:46 PM CeSyncTime 7/10/14 12:30:46 PM SetTime - st: 2014, 7, 10 - 18:30:46.0 CeSyncTime 7/10/14 1:30:46 PM SetTime - SetSystemTimeRetValue: True CeSyncTime 7/10/14 1:30:46 PM SetTime - Diagnostic Infomation - End CeSyncTime 7/10/14 1:30:51 PM Program ended! CeSyncTime 7/10/14 1:31:37 PM Starting Set Time (from 7/10/14 1:31:37 PM to 7/10/14 1:31:37 PM) Version: 5.1.0.8 CeSyncTime 7/10/14 1:31:38 PM SetTime - Diagnostic Infomation - Start CeSyncTime 7/10/14 1:31:38 PM SetTime - CurrentTime: 7/10/14 1:31:37 PM CeSyncTime 7/10/14 1:31:38 PM SetTime - NewTime: 7/10/14 1:31:37 PM CeSyncTime 7/10/14 1:31:38 PM SetTime - DSTTranstions: False CeSyncTime 7/10/14 1:31:38 PM SetTime - DSTTranstionOffset: 0 CeSyncTime 7/10/14 1:31:38 PM SetTime - utc: 7/10/14 6:31:37 PM CeSyncTime 7/10/14 1:31:38 PM SetTime - st: 2014, 7, 10 - 18:31:37.0 CeSyncTime 7/10/14 1:31:37 PM SetTime - SetSystemTimeRetValue: True CeSyncTime 7/10/14 1:31:37 PM SetTime - Diagnostic Infomation - End CeSyncTime 7/10/14 1:31:42 PM Program ended! Br Scanner 7/10/14 1:31:52 PM Started Br Scanner 7/10/14 1:31:52 PM Version 5.1.0.8
Upvotes: 1
Views: 1470
Reputation: 16896
The problem is in this line:
Dim utc As DateTime = #5/9/2014 11:00am#.ToUniversalTime()
The DateTime
literal is evaluated as a DateTime
of kind Unspecified
. When you call ToUniversalTime
the function assumes it was a local time and converts it to 10am UTC.
You could define your time like this instead:
Dim utc as DateTime = DateTime.SpecifyKind(#5/9/2014 11:00am#, DateTimeKind.Utc)
Upvotes: 1