Click here to Skip to main content
Click here to Skip to main content

ZoneInfo (tz Database / Olson Database) .NET API

, 7 Apr 2008 Ms-PL
Rate this:
Please Sign up or sign in to vote.
A simple .NET interface for utilising the ZoneInfo database

Introduction

This article describes a simple .NET API for using the ZoneInfo database, which is also known as the tz database or Olson database.

The API is available here.

I hope you find it useful. Smile | :)

Background

I have been developing a web site which schedules meetings and events across multiple time zones for more than a year now.

I previously used the .NET PublicDomain library discussed in another CodeProject article but had a number of issues including:

  • Just not working for Australia
  • It seems to hard code in the tz database rather than reading it from the file system; therefore if you need to update the database, you need to wait for the source code to be updated
  • The library seems to have a lot of other things in it which I just don't need (which is not a major issue though)

One of the big things I wanted was to have an API by which I can just download the latest tz database and off I go.

I am not a big fan of reinventing the wheel so if this library just isn't needed, PLEASE let me know. Smile | :)

Using the Code

Talking a fairly agile approach to this, I have just implemented the APIs which I have needed.

The interface itself is extremely simple and hopefully is well illustrated by the examples below.

Loading the Data

// Load all the files
Database.LoadFiles(@"c:\src\trunk\TimeZoneTest\tzdata");

Before you start to use any of the functions, you need to make sure that the database of files are loaded.

Right now *.tab files in the timeinfo distribution are not loaded, but they are needed for the current set of APIs.

Getting the Local Time Somewhere Else

// Iterate through all the zone strings
foreach (string zoneName in Database.GetZoneNames())
{
    Zone z = Database.GetZone(zoneName);

    Console.WriteLine("Zone: " + z.Name
                        + "\n\thas a local date time of "
                        + z.Now.ToString()
                        + "\n\twhich is a GMT offset of "
                        + z.GetUtcOffset(z.Now).ToString());
}

The sample above gets all the time zone names and then gets the corresponding ZoneInfo.Zone instance.

From this instance, you can do a number of things like getting the local time in that zone and its current UTC offset.

Zone: Europe/Malta
        has a local date time of 8/04/2008 9:40:52 AM
        which is a GMT offset of 02:00:00
Zone: Europe/Minsk
        has a local date time of 8/04/2008 10:40:52 AM
        which is a GMT offset of 03:00:00
Zone: Europe/Monaco
        has a local date time of 8/04/2008 9:40:52 AM
        which is a GMT offset of 02:00:00
Zone: Europe/Moscow
        has a local date time of 8/04/2008 11:40:52 AM
        which is a GMT offset of 04:00:00 

Convert Times between Time Zones

// What is the time in Sao Paulo when it is new year's day in Melbourne?
Zone melbTz = Database.GetZone("Australia/Melbourne");
Zone spTz = Database.GetZone("America/Sao_Paulo");

DateTime melbTime = new DateTime(2009, 1, 1, 0, 0, 0, DateTimeKind.Local);
DateTime utcTime = melbTz.ConvertToUtc(melbTime);
DateTime spTime = spTz.ConvertToLocal(utcTime);

Console.WriteLine("Melbourne " + melbTime.ToString()
                  + "\nSao Paulo " + spTime.ToString()
                  + "\nUTC " + utcTime.ToString());

One of the most useful features of the API is the ability to convert arbitrary dates between time zones. A lot of TimeZone APIs only really know what the UTC offset is right now, not 6 months from now.

Melbourne 1/01/2009 12:00:00 AM
Sao Paulo 31/12/2008 11:00:00 AM
UTC 31/12/2008 1:00:00 PM

Offset Cut-over Windows

// What are all the timezone cutover windows for Melbourne in the last few years?
List<DateTime> dates =
         melbTz.GetCutoverWindows(
                    new DateTime(2007, 1, 1, 0, 0, 0, DateTimeKind.Local),
                    new DateTime(2009, 12, 31, 23, 59, 59, DateTimeKind.Local));

Console.WriteLine("Printing cutovers between 1/1/2007 - 31/12/2009");
foreach (DateTime dt in dates)
{
     Console.WriteLine("\t" + dt.ToString());
}

This functionality may seem useless ... until you actually need it.

If you store dates in the database in UTC and need to convert them to the local time of the user, you need to apply a UTC offset. What happens if the daylight offset changes within this window? Well, you can know if this is the case rather than assuming that it doesn't matter.

Printing cutovers between 1/1/2007 - 31/12/2009
        30/03/2007 2:00:00 AM
        27/10/2007 2:00:00 AM
        6/04/2008 2:00:00 AM
        5/10/2008 2:00:00 AM
        5/04/2009 2:00:00 AM
        4/10/2009 2:00:00 AM  

Points of Interest

The code seems to work well for Australia and the other zones I have tested this with. I am sure as more people use it in different scenarios, it will continue to mature.

One thing I did notice was just how un-standard the format of the tz database was with respect to tab and space delimiting of fields ... the code has a number of hacks unfortunately to compensate this.

More Information

Check out the latest version of the code on CodePlex.

If you have any issues, please log it there and I will look at any changes which need to get done.

History

  • 7th April, 2008: Initial post

There are still a number of things to be done including handling of Link entries in the files. The current format allows for backward compatibility in the old names. This is not hard to do and will happen soon (or if someone needs it).

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Mark Rodrigues
Chief Technology Officer Attend Anywhere
Australia Australia
I don't get my hands dirty that much any more but enjoy it when I do Smile | :)

Comments and Discussions

 
GeneralThank you for sharing! Pinmemberagatonek29-May-14 9:11 
QuestionDatabase.cs {"Input string was not in a correct format."} Pinmemberdburtsev7-Jun-13 10:02 
AnswerSilverlight Developers Rejoice!!! PinmemberABOHAK23-Feb-12 3:10 
GeneralRe: Silverlight Developers Rejoice!!! PinmemberMark Rodrigues23-Feb-12 12:34 
GeneralImplementation in VB6 Pinmembercptolemy7-Dec-10 9:15 
GeneralRe: Implementation in VB6 PinmemberMark Rodrigues7-Dec-10 11:09 
GeneralMy vote of 2 Pinmemberpooya_p7-Jan-10 22:43 
QuestionGetting time zone info from Windows OS Pinmembermr.sonntag27-Apr-09 22:10 
QuestionGetZoneNames() Pinmemberthaddeusbort4-Sep-08 9:50 
Hello,
 
Thank you for all the work you did to put this API together. The tz database seemed so daunting but your APIs seem to make it very simple to use.
 
Anyway, my problem is that I want to have a list of timezones on my site so that a user can customize their timezone by selecting one from the list. The problem is that GetZoneNames() returns 452 timezones. That list is more than a little intimidating. I'm still very new to how timezones work so don't flame me for asking, but is there a way to only show unique names or anything to get that list smaller? On Flickr.com for example they have a list of 75 timezones to pick from. How would I get a list like that? Or is it just not possible with this database.
 
Thank you,
Ted
AnswerRe: GetZoneNames() PinmemberMark Rodrigues4-Sep-08 14:01 
GeneralRe: GetZoneNames() Pinmemberthaddeusbort10-Sep-08 9:16 
NewsRe: GetZoneNames() PinmemberMark Rodrigues10-Sep-08 13:14 
GeneralDST Not accounted for in ConvertToLocal PinmemberEkHetNieEenNie21-Jul-08 22:18 
GeneralError in negative minute offeset PinmemberWayne Hetherington25-Jun-08 11:12 
AnswerRe: Error in negative minute offeset PinmemberMark Rodrigues4-Sep-08 14:30 
GeneralRe: Error in negative minute offeset PinmemberWayne Hetherington5-Sep-08 5:26 
GeneralRe: Error in negative minute offeset PinmemberMark Rodrigues5-Sep-08 18:43 
GeneralEtc/GMT is altering minutes, not hours PinmemberAbbydonKrafts10-May-08 11:23 
AnswerRe: Etc/GMT is altering minutes, not hours PinmemberMark Rodrigues11-May-08 3:34 
NewsJust updated API and article PinmemberMark Rodrigues7-Apr-08 22:54 
GeneralThe only issue .. PinmemberGarth J Lancaster7-Apr-08 13:28 
GeneralRe: The only issue .. PinmemberMark Rodrigues7-Apr-08 20:26 
GeneralRe: The only issue .. PinmemberGarth J Lancaster7-Apr-08 20:43 
GeneralRe: The only issue .. PinmemberMark Rodrigues7-Apr-08 20:50 
GeneralRe: The only issue .. PinmemberGarth J Lancaster9-Apr-08 2:21 

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 | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 7 Apr 2008
Article Copyright 2008 by Mark Rodrigues
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid