Jon Box's Weblog

 


.NET Articles by the Atomic group

MSDN RDs









Subscribe to "Jon Box's Weblog" in Radio UserLand.

Click to see the XML version of this web page.

Click here to send an email to the editor of this weblog.

 

 

  Wednesday, September 01, 2004


The Problem

Have you ever needed to do date and time manipulation using dates from different time zones?  What about provide a list of time zones?  Could you convert a GMT or even Central time to the 3 different times in Indiana?  Did you know that GMT offsets are not all in increments of an hour?

 

Thanks to a recent project, I got a refresher on time zones, Daylight Saving Time (notice the proper spelling), the weaknesses of the System.DateTime structure, and Win32 API handling of time zones. 

 

In this application, I have a list of events that are happening in different time zones (i.e. some from Eastern, some from Central, some from Pacific, plus more).  The problem is that they are persisted in Memphis as Central times, and the client wants to see this data in the appropriate time zone.  Since this was doing aggregation of event types by date, the data was not correct.  For example, when an event happens at 00:00 (i.e. 12AM) on a Monday in New York (GMT -5:00), it was being recorded here as 11PM on Sunday (GMT -6:00).  And if data was coming from Kathmandu (GMT +5:45), the erroneous data really starts to show.  The customer wanted this changed so that the same activity could be compared at similar hours of the day (i.e. 8AM activities in New York compared to 8AM activities in Kathmandu).

 

Since we know the locations, we believed that we could easily calculate the correct time.  But what about Indiana, Arizona, and Hawaii and their handling of Daylight Saving Time?

 

What Do We Have To Work With?

First, System.DateTime is OK but it has serious issues due to not knowing the kind of date (local or GMT). It also has little time zone support. Pass a DateTime value that is currently GMT based to the ToUniversalTime function and watch the bad data happen.  This is due to the function expecting a local time.

 

Side note: The V2 DateTime does a little to fix the kind issue by providing a DateTimeKind enum and SpecifyKind method.  The V2 conversion functions also look at this to make better calculations.  But, I have to make this work in v1.1.

 

Second, System.DateTime includes no assistance for converting times across time zones.  Furthermore, there is no way to enumerate the time zones supported in Windows.  And neither of these is addressed in V2.  To me, since there is so much Date and Time support in the Win32 API and in the C runtime, then .NET should have at least the same functionality and when possible even better.

 

As I said earlier, we could add a GMT offset and Daylight Saving Time flag to the database to indicate if that customer location follows Daylight Saving Time.  Then, it was a matter of using adding a TimeSpan to the DateTime from the log.  But, this type of work has already been done in Win32, so I felt that there had to be a better way.

 

I really wanted a couple of things. 1) A way to show the list of time zones (like the way you see it when you’re setting up your Windows date, time, and timezone). 2) An easy way to convert Central time to a time of the specific location.

 

The Solution

After some searching, I found some managed wrapper classes from Art Wallace of Crankedup.Com. He has some other interesting samples as well.  But, his timezone conversion library is just what the doctor ordered.  It is a slightly improved update of a sample by Arin Goldade, who provided his library on GotDotNet.  The class provides a way to get the list of time zones from the registry of your Windows machine, a way to convert times across time zones, and more.  It is a nice wrapper around some Win32 functionality that should be in .NET.  Art’s improvements make it easier to add functionality to Arin’s work.

 

My additions to the classes and structures are:

- added a Key property to the TimeZoneInfo in order for later specific requests.  The Key is actually the registry subkey, like “Central Standard Time”.  Under this key, there are all sorts of goodies specific to the time zone.  We store this registry subkey in our database for later retrieval during conversions.  Art also collected the “display” entry from the registry, which is the value shown on the Windows UI when selecting a time zone.

- added a TimeZoneInfo::GetSystemTimeInfo(string Key) method in order for an assembly to load a specific TimeZone by using a Key.

- rename the library to Win32TimeZoneLibrary.

 

I am now able to do something like this:

 

Dim centralTZI As Win32TimeZoneLibrary.TimeZoneInfo = _

      Win32TimeZoneLibrary.TimeZoneInfo.GetSystemTimeZone("Central Standard Time")

 

Dim tziDest As Win32TimeZoneLibrary.TimeZoneInfo = _
      Win32TimeZoneLibrary.TimeZoneInfo.GetSystemTimeZone(”Nepal Standard Time”)

 

Dim dtDest As DateTime = _

      Win32TimeZoneLibrary.TimeZoneInfo.Convert( _

                                centralTZI, _

                                tziDest, _

                                dtCentral)

 

Hopefully, I just showed that converting Memphis time to Kathmandu time does not take a lot of code to work.  Furthermore, when allowing the user to do location maintenance like choosing the time zone, we display the same list as you see when changing the time zone in windows. 

 

C’mon BCL Team, it’s not too late to enhance the DateTime structure!


2:53:20 AM    comment []


Click here to visit the Radio UserLand website. © Copyright 2004 Jon Box.
Last update: 10/17/2004; 2:25:23 AM.

September 2004
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Aug   Oct