Dan Rigsby - Coding Up Style

Developer.Speaker.Blogger

TimeZone vs. TimeZoneInfo in .Net

Posted by Dan Rigsby on August 24th, 2008

Working with Dates and Times in .Net 3.5 Series:
Part 1: DateTime vs. DateTimeOffset in .Net
Part 2: TimeZone vs. TimeZoneInfo in .Net

This is Part 2 in a series on working with Dates and Times in .Net 3.5.  You might want to read Part 1: DateTime vs. DateTimeOffset in .Net in WCF before continuing on with this post.

MoonKnt_12The TimeZone data type was introduced in .Net 1.0 as a mechanism for retrieving information about the current time zone, and to convert times from local time to Coordinated Universal Time (UTC) or vice versa.  The down side is that you cannot use this to represent any other time zone other than the local zone.  It also can’t be used to convert one date time to another zone.  This is a pretty sever limitation and something that .Net has been lacking for some time.

In .Net 3.5, Microsoft finally introduced a replacement for TimeZone.  The TimeZoneInfo class fills in all of the gaps where TimeZone left off.  You can represent any time zone and perform various calculations.  Many people have yet to hear of this class, but it is crucial if you are working with applications that need to perform calculations on dates and times which may originate from differet time zones. The major functions of this class include the ability to:

  • Retrieving a time zone that is already defined by the operating system. This can be retrieved by ID or the current local time zone.
  • Converting times between different time zones.
  • Enumerating the time zones that are available on a system.
  • Find all time zones a DateTime or DateTimeOffset can represent.
  • Creating a new time zone that is not already defined by the operating system.
  • Serializing a time zone for later retrieval.

View the complete list of members here: http://msdn.microsoft.com/en-us/library/system.timezoneinfo_members.aspx

Use this class to work with any time zone that is predefined on a system, to create new time zones, and to easily convert dates and times from one time zone to another. The TimeZoneInfo class replaces the TimeZone class in every way.  For all new development, ignore the TimeZone class and move straight to TimeZoneInfo.  The TimeZone class should probably have been marked as “Obsolete”.

How TimeZone class works

TimeZone timeZone = System.TimeZone.CurrentTimeZone;
Console.WriteLine(timeZone.StandardName);
 
With the TimeZone class you could pull the current time zone with the static CurrentTimeZone static property.  The TimeZone class has no constructors and fairly limited use.  You can convert dates and times from the local zone to UTC, but you have no access to other time zones.

How to retrieve a time zone with TimeZoneInfo

TimeZoneInfo hwZone =
    TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
TimeZoneInfo info = TimeZoneInfo.Local;
 
The TimeZoneInfo class allows you to access the local time zone with the Local static property.  This is similar to the TimeZone class.  However, TimeZoneInfo also allows you to reference any time zone with the FindSystemTimeZoneById static method. This method takes in a string which represents the Id for the time zone. Once you have this time zone, you can work with methods on the object to perform a variety of conversions.
 
A TimeZoneNotFoundException is thrown if the time zone ID could not be found on the local system.

How to convert times between different time zones with TimeZoneInfo

The TimeZoneInfo provides a few conversion methods to allow conversions between different time zones.  The most useful of which is the ConvertTime method.  With this, you can pass in a date/time and the time zone in which you want to convert it into.  If you are using DateTimeOffset, then when you compare the two date/time values, they are equivalent since they both represent the same time, just in different time zones.

DateTimeOffset nowDateTime = DateTimeOffset.Now;
DateTimeOffset newDateTime = TimeZoneInfo.ConvertTime(
    nowDateTime,
    TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time"));
Console.WriteLine("Now: {0}", nowDateTime);
Console.WriteLine("Now in Hawaii: {0}", newDateTime);
 
timezoneinfo1 

How to enumerate through all time zones on the computer with TimeZoneInfo

The GetSystemTimeZones method of the TimeZoneInfo class returns a ReadOnlyCollection of all of the time zones that the current system knows about.

ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
Console.WriteLine("All time zones:");
foreach (TimeZoneInfo timeZoneInfo in timeZones)
{
    Console.WriteLine("   {0}", timeZoneInfo.DisplayName);
}

timezoneinfo2 

How to find all time zones a DateTime or DateTimeOffset can represent with TimeZoneInfome

Most date time offset can represent multiple time zones.  For instance, if a date and time have a –6 hour offset, this could be in the Central Time, Central American, Saskatchewan, or Guadalajara.  With the TimeZoneInfo class, you can easily find all of the time zones that the date and time could represent by simply interating over all of the time zones on the system and comparing their offset to the offset stored in the DateTimeOffset object:

DateTimeOffset current = DateTimeOffset.Now;
ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
Console.WriteLine("You might be in the following time zones:");
foreach (TimeZoneInfo timeZoneInfo in timeZones)
{
    // Compare offset with offset for that date in that time zone
    if (timeZoneInfo.GetUtcOffset(current).Equals(current.Offset))
    {
        Console.WriteLine("   {0}", timeZoneInfo.DisplayName);
    }
}
 
This code outputs all of the following time zones.  DateTimeOffset.Now happens to represent “Eastern Time” in this example.
 
timezoneinfo3 

How to create a new time zone with TimeZoneInfo

The TimeZoneInfo class has no constructors, so it is impossible to new up a new instance.  However, it does provide a static method called CreateCustomTimeZone that allows you to create a new time zone to work with.  This method has a couple of overrides to provide you with everything needed to create a new time zone.  The following creates a new simple time zone called “My Custom Time Zone” which has a –4 hour offset from GMT and observes daylight savings time.

TimeZoneInfo info = TimeZoneInfo.CreateCustomTimeZone(
    "My Custom Time Zone",
    new TimeSpan(-4, 0, 0),
    "My Custom Time Zone",
    "My Custom Time Zone",
    "My Custom Time Zone",
    new TimeZoneInfo.AdjustmentRule[] { },
    false);

How to serialize a time zone with TimeZoneInfo

One of the unique features of the TimeZoneInfo class is that it has a native method to serialize the time zone to a string.  The ToSerializedString method is unlike other serialization methods in that it doesn’t serialize to xml by default, but instead to a semicolon delimited list.  This serialized string can be stored to disk or some other location for later retrieval.

TimeZoneInfo info = TimeZoneInfo.Local;
string serialized = info.ToSerializedString();
 
This code produces the following output:

Eastern Standard Time;-300;(GMT-05:00) Eastern Time (US & Canada);Eastern Standard Time;Eastern Daylight Time;[01:01:0001;12:31:2006;60;[0;02:00:00;4;1;0;];[0;02:00:00;10;5;0;];][01:01:2007;12:31:9999;60;[0;02:00:00;3;2;0;];[0;02:00:00;11;1;0;];];

To deserialize the string back into a TimeZoneInfo class, you can use the FromSerializedString static method to create a new TimeZoneInfo object.

TimeZoneInfo info2 = TimeZoneInfo.FromSerializedString(serialized);
DotNetKicks Image

6 Responses to “TimeZone vs. TimeZoneInfo in .Net”

  1. Dan Rigsby » DateTime vs. DateTimeOffset in .Net Says:

    [...] Posted by Dan Rigsby on August 23rd, 2008 Working with Dates and Times in .Net 3.5 Series: Part 1: DateTime vs. DateTimeOffset in .Net Part 2: TimeZone vs. TimeZoneInfo in .Net [...]

  2. Weekly Web Nuggets #27 : Code Monkey Labs Says:

    [...] TimeZone vs. TimeZoneInfo In .NET 3.5: In part two, Dan takes a look at the new TimeZoneInfo class. [...]

  3. Dan Rigsby » New Webcast: Date & Times in .Net 3.5 Says:

    [...] TimeZone vs. TimeZoneInfo in .Net [...]

  4. Weekly Link Post 57 « Rhonda Tipton’s WebLog Says:

    [...] Dan Rigsby continues his series on Working with Dates & Times in .Net 3.5: TimeZone vs. TimeZoneInfo in .Net [...]

  5. Steve Says:

    Hi Dan,
    I have to use .Net 2.0 for now.
    I have a WinForms app that needs to simultaneously show times for our 3-4 offices around the world, so everyone running it will see the times at all offices, regardless of what time zone the client computer is in. Given DateTime.Now, I was hoping the .ToString() method would take an optional timezone parameter, but no such luck.

    Do you have any suggestions for how to do this in .NET 2.0. It looks like support is better in 3.5, but I can’t go there yet.

    Thanks in advance,
    Steve

  6. Dan Rigsby Says:

    You have a number of options. If you are storing the date at UTC, then you just need to call ToLocalTime(). If you arent using UTC times, then you need to somehow send the offset (from GMT) to the clients. This can be a global variable you store if this doesnt change. A offset might be -4 hours. Then you can just use the DateAdd methods to add the positive or negative number to calculate the offset.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>