TimeZoneInfo と DateTimeOffset

皆さん、こんにちは

前回お約束した通り、少しずつではありますがTechEdでのDEMOのフォローをしていきたいと思います。

今回は.NET Framework 3.5 で改善された TimeZone への対応について紹介したいと思います。今回、ご紹介するのは DateTimeOffset と TimeZoneInfo です。今まで DateTime では Local のTimeZone と UTC のみの対応となっていましたが、今回の変更で それ以外の TimeZone 情報を扱うことができるようになりました。

まずは TimeZoneInfo ですが、こちらは Windows のレジストリに登録されている TimeZone 情報を扱うためのクラスです。下の DEMO の例では"Pacific Standard Time" という ID のTimeZone をレジストリから探してきて、変換を行っています。

次に DateTimeOffset ですが、下の DEMO の「変更点1」と「変更点2」の箇所を DateTime のまま実行した場合、 TimeZoneInfo を使用して変換をおこなっても、変更後のDateTime の TimeZone は Local 環境のままです。つまり、UTCの時間も現在時刻ではない時刻に変更されてしまっています。そこでDateTimeOffsetを利用すると、この問題が解決します。「変更点1」と「変更点2」の DateTime を DateTimeOffset に変更して実行してみてください。TimeZoneInfo での変換の際にTimeZoneOffset のTimeZone も変更されています。これにより、UTC の時刻は変更されず、TimeZone の適用だけが変更されます。

using System;

public class TimeZoneInfoSample
{

    private static string dtFormat = "yyyy/MM/dd HH:mm:ss";

    private static void Main()
    {

        DateTime dt1 = DateTime.Now; // 変更点1
        DateTime dt2; // 変更点2
        TimeZoneInfo tzi;

        try
        {
            //レジストリからアメリカ 太平洋標準時間をタイムゾーン情報を取得
            tzi = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
        }
        catch (TimeZoneNotFoundException ex) { throw ex; }
        catch (InvalidTimeZoneException ex) { throw ex; }

        //TimeZoneを変換する
        dt2 = TimeZoneInfo.ConvertTime(dt1, tzi);

        Console.WriteLine("日本時間--------LocalTime:{0}  UTC:{1}",
            dt1.ToString(dtFormat), dt1.ToUniversalTime().ToString(dtFormat));
        Console.WriteLine("太平洋標準時間--LocalTime:{0}  UTC:{1}",
            dt2.ToString(dtFormat), dt2.ToUniversalTime().ToString(dtFormat));
        Console.ReadKey();

    }
}

と今回は TimeZone への対応をご紹介いたしました。この辺の情報は BCL チームのこのエントリ(英語)がひじょうに参考になります。お時間があれば是非ご一読ください。

次回は、またネタを見繕ってご紹介したいと思います。