How to read TimeZone Information from the windows registry with VB.Net TZI

50 views
Skip to first unread message

tw_scannell

unread,
Nov 17, 2009, 11:55:01 AM11/17/09
to DotNetDevelopment, VB.NET, C# .NET, ADO.NET, ASP.NET, XML, XML Web Services,.NET Remoting
I spent a week figuring this out. I actually populate an arraylist of
class objects that contain all of the data. They are listed at the
bottom.

Note' the registry path is different for pre win 2000 systems. This
work on 2000 xp vista and windows7

Good Luck TW Scannell (all one word, at that gmail place)


Public Enum enmTZI_Reg_Map
GMT_Bias = 0
Std_Bias = 4
Dlt_Bias = 8
STD_Year = 12
STD_Month = 14
STD_Day_of_Week = 16
STD_Day = 18
STD_Hour = 20
STD_Minute = 22
STD_Second = 24
STD_Milliseconds = 26
DLS_Year = 28
DLS_Month = 30
DLS_Day_of_Week = 32
DLS_Day = 34
DLS_Hour = 36
DLS_Minute = 38
DLS_Second = 40
DLS_Milliseconds = 42
End Enum


############### Classes ################

Make a class named Class_TimeZoneInfo with public properties for the
following items

Private mBias As Integer '
Private mStandardBias As Integer '
Private mDaylightBias As Integer '
Private mStandardDate As CLass_SystemTime '
Private mDaylightDate As CLass_SystemTime '
Private mDisplayName As String '
Private mStandardName As String '
Private mDaylightName As String '
Private mMapID As String '
Private mAbbreviation As String
Private mSupportsDaylightSavingTime As Boolean


also a class named CLass_SystemTime, like so to use in mStandardDate
and mDaylightDate above.

Private mwYear As Short '
Private mwMonth As Short '
Private mwDayOfWeek As Short '
Private mwDay As Short '
Private mwHour As Short '
Private mwMinute As Short '
Private mwSecond As Short '
Private mwMilliseconds As Short '

############### Function ################
Declarations (Class level)
Private mTimeZoneArray As ArrayList

Public Function fncEnumSubKeys() As Boolean
On Error GoTo ErrorHandle : Dim CmdProc As Boolean : CmdProc =
False

Dim LoopCount As Integer
Dim TZLoop As Integer
Dim TimeZonesArray As Array
Dim TZValuesArray As Array

Dim TimeZonesKey As Microsoft.Win32.RegistryKey
Dim TZValuesKey As Microsoft.Win32.RegistryKey

Dim PathString As String
Dim BuildString As String = ""

Dim MyTimeZoneInfo As Class_TimeZoneInfo
Dim ByteMe() As Byte

TimeZonesKey = My.Computer.Registry.LocalMachine.OpenSubKey
("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones")
TimeZonesArray = TimeZonesKey.GetSubKeyNames()
TimeZonesKey.Close()

For LoopCount = 0 To UBound(TimeZonesArray)
MyTimeZoneInfo = New Class_TimeZoneInfo

TZValuesKey = My.Computer.Registry.LocalMachine.OpenSubKey
("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" &
TimeZonesArray(LoopCount).ToString)
TZValuesArray = TZValuesKey.GetValueNames
PathString = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
\Windows NT\CurrentVersion\Time Zones\" & TimeZonesArray
(LoopCount).ToString

For TZLoop = 0 To UBound(TZValuesArray)

Select Case UCase(TZValuesArray(TZLoop).ToString)
Case "DISPLAY"
MyTimeZoneInfo.DisplayName =
My.Computer.Registry.GetValue(PathString, TZValuesArray
(TZLoop).ToString, "")

Case "DLT"
MyTimeZoneInfo.DaylightName =
My.Computer.Registry.GetValue(PathString, TZValuesArray
(TZLoop).ToString, "")

Case "STD"
MyTimeZoneInfo.StandardName =
My.Computer.Registry.GetValue(PathString, TZValuesArray
(TZLoop).ToString, "")

Case "MAPID"
MyTimeZoneInfo.MapID =
My.Computer.Registry.GetValue(PathString, TZValuesArray
(TZLoop).ToString, "")

Case "TZI"

ByteMe = My.Computer.Registry.GetValue
(PathString, TZValuesArray(TZLoop).ToString, Nothing)

MyTimeZoneInfo.Bias = (BitConverter.ToInt16
(ByteMe, enmTZI_Reg_Map.GMT_Bias))
MyTimeZoneInfo.StandardBias =
(BitConverter.ToInt16(ByteMe, enmTZI_Reg_Map.Std_Bias))
MyTimeZoneInfo.DaylightBias =
(BitConverter.ToInt16(ByteMe, enmTZI_Reg_Map.Dlt_Bias))

With MyTimeZoneInfo.StandardDate
.wYear = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Year))
.wMonth = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Month))
.wDayOfWeek = (BitConverter.ToInt16
(ByteMe, enmTZI_Reg_Map.STD_Day_of_Week))
.wDay = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Day))
.wHour = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Hour))
.wMinute = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Minute))
.wSecond = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.STD_Second))
.wMilliseconds = (BitConverter.ToInt16
(ByteMe, enmTZI_Reg_Map.STD_Milliseconds))
End With

With MyTimeZoneInfo.DaylightDate
.wYear = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Year))
.wMonth = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Month))
.wDayOfWeek = (BitConverter.ToInt16
(ByteMe, enmTZI_Reg_Map.DLS_Day_of_Week))
.wDay = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Day))
.wHour = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Hour))
.wMinute = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Minute))
.wSecond = (BitConverter.ToInt16(ByteMe,
enmTZI_Reg_Map.DLS_Second))
.wMilliseconds = (BitConverter.ToInt16
(ByteMe, enmTZI_Reg_Map.DLS_Milliseconds))

MyTimeZoneInfo.SupportsDaylightSavingTime
= (.wYear + .wMonth + .wDayOfWeek + .wDay + .wHour + .wMinute
+ .wSecond + .wMilliseconds) > 0

End With

End Select

mTimeZoneArray.Add(MyTimeZoneInfo)

Next

TZValuesKey.Close()
Next

fncEnumSubKeys = CBool(Err.Number = 0)

End Function




!!The discussion below is about other code that you might try, but it
didn't work for me.
Stop reading now unless you really want to peel the onion!!

As of Nov/16 2009 using VB.Net 3.5, SupportsDaylightSavingTime gives
contradicting results for 3 time zones.

Arabic Standard Time
Morocco Standard Time
Pakistan Standard Time

The SupportsDaylightSavingTime value is reported as True for these 3,
however if you look at the Daylight start times and dates, they are
all 0.
Because of that I populate my
Class_TimeZoneInfo.SupportsDaylightSavingTime by adding all the
daylight dates and time together and compare them to 0.

along that line, I also found some other objects,(see below) but the
data that these return is random and inacurate.
Particularly "Arabic Standard Time", "Morocco Standard Time",
"Pakistan Standard Time"
These Usee the 2008 Dynamic data and get values that contradict what
is in the Main TZI part of the registry (as of Nov of 2009).
Ironically the 2008 values are correct as far is what actually
happened in those counties, but the windows timezone selection screen
for XP and windows7 showed the 2009 values.(The screen you get when
you want to change your system timezone from the control panel)
Those incorrect 2009 values stated that there was no DST in these 3
areas, which is false in all 3 cases.
Irregardless (my favorite non-word) I choose to match what the System
says, expecially since there where other major descrepancies with the
code below.

The ToSerializedString returns all the TZI data including the Dynamic
DST but it is dificult to parse
Somewhere I played with a second "serialize" string that was also
inacturate.

Public Function fncBogusTimeZoneData() As Boolean
Dim myArray As New ArrayList
Dim LoopCount As Integer
Dim myZone As System.TimeZoneInfo
Dim HighTime As Date
Dim returnValue As TimeSpan
Dim BuildString As String = ""
Dim AddRule() As System.TimeZoneInfo.AdjustmentRule
Dim MyTransTime As System.TimeZoneInfo.TransitionTime

myArray.AddRange(System.TimeZoneInfo.GetSystemTimeZones())

For LoopCount = 0 To myArray.Count - 1
myZone = myArray(LoopCount)

BuildString += "DisplayName " &
myZone.DisplayName & vbCrLf
BuildString += "StandardName " &
myZone.StandardName & (vbCrLf)
BuildString += "Id " & myZone.Id &
vbCrLf
BuildString += "DaylightName " &
myZone.DaylightName & (vbCrLf)
BuildString += "IsDaylightSavingTime " &
myZone.IsDaylightSavingTime(HighTime) & vbCrLf
BuildString += "BaseUtcOffset " &
myZone.BaseUtcOffset.ToString & (vbCrLf)

returnValue = myZone.GetUtcOffset(HighTime)
BuildString += "GetUtcOffset " &
returnValue.ToString & vbCrLf & vbCrLf

BuildString += "SupportsDaylightSavingTime " &
myZone.SupportsDaylightSavingTime & vbCrLf
BuildString += myZone.ToSerializedString & vbCrLf
AddRule = myZone.GetAdjustmentRules()

If AddRule.Length > 0 Then

MyTransTime = AddRule(0).DaylightTransitionStart
With MyTransTime.TimeOfDay
BuildString += "year" & ":" & .Hour & ":"
& .Minute & ":" & .Second & ":" & .Millisecond & ":" &
MyTransTime.Month & ":" & MyTransTime.Day & ":" &
MyTransTime.DayOfWeek & vbCrLf

BuildString += "DaylightTransitionStart.Month = "
& MyTransTime.Month & vbCrLf
BuildString += "DaylightTransitionStart.Day = " &
MyTransTime.Day & vbCrLf
BuildString += "DaylightTransitionStart.DOW = " &
MyTransTime.DayOfWeek & vbCrLf
BuildString += "DaylightTransitionStart.Hour = " &
MyTransTime.TimeOfDay.Hour & vbCrLf
BuildString += "DaylightTransitionStart.Minute = "
& MyTransTime.TimeOfDay.Minute & vbCrLf
BuildString += "DaylightTransitionStart.Second = "
& MyTransTime.TimeOfDay.Second & vbCrLf
BuildString +=
"DaylightTransitionStart.Millisecond = " &
MyTransTime.TimeOfDay.Millisecond & vbCrLf
End With

MyTransTime = AddRule(0).DaylightTransitionEnd
With MyTransTime.TimeOfDay
BuildString += "year" & ":" & .Hour & .Minute &
":" & .Second & ":" & .Millisecond & ":" & MyTransTime.Month & ":" &
MyTransTime.Day & ":" & MyTransTime.DayOfWeek & vbCrLf

BuildString += "DaylightTransitionEnd.Month = " &
MyTransTime.Month & vbCrLf
BuildString += "DaylightTransitionEnd.Day = " &
MyTransTime.Day & vbCrLf
BuildString += "DaylightTransitionEnd.DOW = " &
MyTransTime.DayOfWeek & vbCrLf
BuildString += "DaylightTransitionEnd.Hour = " &
MyTransTime.TimeOfDay.Hour & vbCrLf
BuildString += "DaylightTransitionEnd.Minute = " &
MyTransTime.TimeOfDay.Minute & vbCrLf
BuildString += "DaylightTransitionEnd.Second = " &
MyTransTime.TimeOfDay.Second & vbCrLf
BuildString += "DaylightTransitionEnd.Millisecond
= " & MyTransTime.TimeOfDay.Millisecond & vbCrLf
End With

Application.DoEvents()

End If

BuildString += vbCrLf & vbCrLf
Next

TextBox2.Text = BuildString
End Function
Reply all
Reply to author
Forward
0 new messages