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