Click here to Skip to main content
Click here to Skip to main content
Go to top

TimeZone Dialog

, 14 Mar 2009
Rate this:
Please Sign up or sign in to vote.
An article for creating a timezone dialog form
TimeZoneForm

TimeZoneForm

Introduction

This article explains how to pick timezone from Windows registry and sort it for displaying purposes.

A time zone is a region of the earth that has the same standard time. All areas within that region will apply the same time. Because of the earth's spherical shape and the rotation of the earth, generally there are 24 regions with each region having a difference of 1 hour. But some occasions arise in some areas whereby it has a different time from that which its region should have.

Background

When I designed my analog control, I decided to add timezone feature which made my control. A time zone dialog which works exactly like Windows time would be good enough. That's when I started to observe where Windows stores this information. After digging several sources, I found it stored in the registry, but then I realized that it would not be as easy as just reading the data. The process of making the timezone dialog is just as complex as creating the analog control itself.

While you set your time, you will see a time zone tab in the dialog. Alternatively, you can see Windows standard time zones in regional setting in control panel. In that dialog, you'll see a list of standard time zones. Our primary goal in this article is to retrieve the values and mimic its functionality.

Making the Code

The main object of this code is TimeZones structure. The structure will have data from each timezone, including name and timespan. The processing will be done by TimeZoneForm.

Preparation

Our first preparation is to know where Windows stores this time zone list. It is stored in the registry, at "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\". In that key, there are many sub keys which provide information about each time zone. So, to retrieve the time zone list, we will look at these sub keys and read their values.

Design Basic Fundamentals

The first thing we should do is create a Time Zone structure that will contain time zone data. We don't need a class because it's only for displaying data and light processing. Besides, we will use a generic collection to store all time zone structures.

Private Structure TimeZones
    Private _Display As String
    Private _Name As String
    Private _TimeSpan As TimeSpan

    Public Property DisplayName() As String
        Get
            Return _Display
        End Get
        Set(ByVal value As String)
            _Display = value
        End Set
    End Property

    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property

    Public ReadOnly Property Span() As TimeSpan
        Get
            Return _TimeSpan
        End Get
    End Property
End Structure

Next, we will analyze how time zone structures are in the registry where Windows stored them. As I told earlier, Windows stores time zone data in "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\". Each time zone data is stored on a sub key. In sub key, there are 4 string values, a dword values and a binary value. Basically, we need only one key which is a display value. The display key will be added in our time zone structures. From this display data, we will set time span for the time zone as well. To validate a time zone's time span, we will parse directly from display value. Display value will have data like this: "(GMT+07:00) Bangkok, Hanoi, Jakarta". In order to get time span, we will parse "(GMT+07:00)" in order to get 07:00 value. A new function will be needed to parse this information, so we add it in Time Zone structure.

Private Sub ValidateTimeSpan()
    'Example: (GMT+07:00)
    Try
        Select Case Mid(_Display, 5, 1)
            Case ")" 'GMT
                _TimeSpan = New TimeSpan(0, 0, 0)
            Case "+"
                _TimeSpan = New TimeSpan(CInt(Mid _
(_Display, 6, 2)), CInt(Mid(_Display, 9, 2)), 0)
            Case "-"
                _TimeSpan = New TimeSpan(CInt(Mid_
(_Display, 6, 2)) * -1, CInt(Mid(_Display, 9, 2)) * -1, 0)
        End Select
    Catch ex As Exception
        'GMT will raise an error. So we place it here.
        _TimeSpan = New TimeSpan(0, 0, 0)
    End Try
End Sub

Now our base structure is ready to use. It's time to implement it in our class. For this sample, I'll use a form and a combo box for generating time zones.

Collect and Process Data for Display

What we have to do now is to initialize a collection variable that contains time zones. We will use System.Collections.Generic.List for generating a list of TimeZones. In the next step, we will fill the collection in our list from Windows registry. To access the registry, we will need Registry library.

Private c As New System.Collections.Generic.List(Of TimeZones)

Private Sub GenerateTimezone()
    Dim rk As RegistryKey = _
    Registry.LocalMachine.OpenSubKey( _
    "SOFTWARE\" & _
    "Microsoft\Windows NT\" & _
    "CurrentVersion\Time Zones\", _
    True)

    For Each sName As String In _
        rk.GetSubKeyNames

        Dim tempKey As _
        RegistryKey = _
        rk.OpenSubKey(sName, True)

        Dim _tz As New TimeZones
        _tz.DisplayName = _

        CType(tempKey.GetValue(_
        "Display"), String)

        _tz.Name = _
        CType(tempKey.GetValue("Std"), String)

        c.Add(_tz)
    Next
End Sub

Now we have our list filled with Time Zones information. Unfortunately, the list is not ordered like it should be. Also, the time zone ordering is not done alphabetically. It is ordered by time span. Since standard collection class doesn't provide us with that kind of sorting, we have to make one by ourselves.

Private Function TimeZoneConvert(ByVal str As String) _
As String
    If Mid(str, 5, 1) = ")" Then
        Return "0"
    Else
        Return Mid(str, 5, 3) & Mid(str, 9, 2)
    End If
End Function

Private Function CompareTimezones(_
ByVal tz1 As TimeZones, _
ByVal tz2 As TimeZones) As Integer
    If IsNothing(tz1) Then
        If IsNothing(tz2) Then
            Return 0
        Else
            Return -1
        End If
    Else
        If IsNothing(tz2) Then
            Return 1
        Else
            Dim int1 As Integer = _
            CInt(TimeZoneConvert(tz1.DisplayName))

            Dim int2 As Integer = _
            CInt(TimeZoneConvert(tz2.DisplayName))

            If int1 > int2 Then
                Return 1
            ElseIf int1 < int2 Then
                Return -1
            Else
                Return 0
            End If
        End If
    End If
End Function

Private Sub DisplayTimeZones()
    cmbTimezone.Items.Clear()

    c.Sort(AddressOf CompareTimezones)

    For Each tz As TimeZones In c
        cmbTimezone.Items.Add(tz.DisplayName)
        If TimeZone.CurrentTimeZone.StandardName = _
        tz.Name Then
            cmbTimezone.Text = tz.DisplayName
        End If
    Next
End Sub

The last one is to add a feature that will enable you to decide your own time. The modification code looks like the one described below:

TimeZoneForm

Public ReadOnly Property NewSpan() As TimeSpan
    Get
        If chkOwn.Checked = False Then
            Return -TimeZone.CurrentTimeZone.GetUtcOffset(Now) + _
				c.Item(cmbTimezone.SelectedIndex).Span
        Else
            Dim ts As TimeSpan
            If rAscend.Checked = True Then
                ts = New TimeSpan(CInt(Mid(mtbValue.Text, 1, 2)), _
				CInt(Mid(mtbValue.Text, 4, 2)), 0)
            ElseIf rDecend.Checked = True Then
                ts = New TimeSpan(CInt(Mid(mtbValue.Text, 1, 2)) * -1, _
				CInt(Mid(mtbValue.Text, 4, 2)) * -1, 0)
            End If
            Return ts
        End If
    End Get
End Property

Using the Code

The TimeZoneForm should act as a dialog form. It will return the latest time after you setup your current time with the new timezone settings. Doing so, the TimeZoneForm will calculate and do the processing and return the expected value.

Points of Interest

There's something that's still on my mind, that is Daylight Saving Time. Since I do not live in a country with Daylight Saving Time, I stripped that feature because I still don't know exactly how it works. There's a subkey in each region that has DST settings and I don't have any idea of how to use it. If anyone could make some modifications or give me some information, I will gladly update my code.

History

  • Version 1.0 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

michaelrawi
Team Leader Component Crafts
Indonesia Indonesia
Got his BA in Information and Technology from University of Surabaya, Indonesia in 2004. Finished his post graduate at Magistrate and Management Institute of Technology, Surabaya in 2009.
 
He has developed several middle to large scale enterprise application, mostly on windows based architecture.
 
Currently working as IT Manager on a company based on Sidoarjo.

Comments and Discussions

 
QuestionWhy? Pinmembersleupold17-Mar-09 0:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140921.1 | Last Updated 14 Mar 2009
Article Copyright 2009 by michaelrawi
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid