連載
» 2015年07月08日 05時00分 UPDATE

.NET TIPS:タイムゾーンから時差を求めるには?[C#、VB]

TimeZoneInfoクラスを利用して、Windowsが保持しているタイムゾーン情報を取得し、そこから時差を求める方法を解説する。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Platform Development]
.NET TIPS
Insider.NET

 

「.NET TIPS」のインデックス

連載目次

対象:.NET 3.5以降


 時差を扱うプログラムではDateTimeOffset構造体を使えばよい(「.NET TIPS:DateTimeとDateTimeOffsetの違いとは?[C#、VB]」)。だが、その時差はどのようにして与えればよいのだろうか? プログラム側にテーブルを持ってもよいが、夏時間があると厄介になる。夏時間の開始日時/終了日時もテーブルに持たなければならないからだ。ところで、Windowsは世界各地のタイムゾーンの情報を持っている。タイムゾーン情報には夏時間の情報も含まれているので、その情報が利用できれば簡単にプログラミングできるだろう。本稿では、Windowsが持っているタイムゾーン情報から時差を求める方法を解説する。

タイムゾーンから時差を求めるには?

 Windowsシステムが持っているタイムゾーンの情報は、TimeZoneInfoクラス(System名前空間)を通じて利用できる。時差を取得するには、まずタイムゾーンのID文字列をTimeZoneInfoクラスのFindSystemTimeZoneById静的メソッドに与えてTimeZoneInfoオブジェクトを取得し、次に引数に時差を求めたい時刻を指定してGetUtcOffsetメソッドを呼び出せばよい(次のコード)。夏時間の調整も含めて、UTC(世界協定時)からの時差を正しく返してくれる。

// 夏時間のあるTimeZoneInfoオブジェクト、例としてPST(太平洋標準時)の情報を取得する
var tzPst = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

// 夏時間終了1秒前(現地時間ではAM1:59:59)
var u1 = new DateTimeOffset(2015, 11, 1, 8, 59, 59, TimeSpan.Zero);
var o1 = tzPst.GetUtcOffset(u1);
Console.WriteLine("Offset at {0:yyyy/MM/dd HH:mm}(UTC) = {1} hours", u1, o1.Hours);
// 出力: Offset at 2015/11/01 08:59(UTC) = -7 hours

// 夏時間終了直後(現地時間ではAM1:00:00)
var u2 = new DateTimeOffset(2015, 11, 1, 9, 0, 0, TimeSpan.Zero);
var o2 = tzPst.GetUtcOffset(u2);
Console.WriteLine("Offset at {0:yyyy/MM/dd HH:mm}(UTC) = {1} hours", u2, o2.Hours);
// 出力: Offset at 2015/11/01 09:00(UTC) = -8 hours

' 夏時間のあるTimeZoneInfoオブジェクト、例としてPST(太平洋標準時)の情報を取得する
Dim tzPst = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")

' 夏時間終了1秒前(現地時間ではAM1:59:59)
Dim u1 = New DateTimeOffset(2015, 11, 1, 8, 59, 59, TimeSpan.Zero)
Dim o1 = tzPst.GetUtcOffset(u1)
Console.WriteLine("Offset at {0:yyyy/MM/dd HH:mm}(UTC) = {1} hours", u1, o1.Hours)
' 出力: Offset at 2015/11/01 08:59(UTC) = -7 hours

' 夏時間終了直後(現地時間ではAM1:00:00)
Dim u2 = New DateTimeOffset(2015, 11, 1, 9, 0, 0, TimeSpan.Zero)
Dim o2 = tzPst.GetUtcOffset(u2)
Console.WriteLine("Offset at {0:yyyy/MM/dd HH:mm}(UTC) = {1} hours", u2, o2.Hours)
' 出力: Offset at 2015/11/01 09:00(UTC) = -8 hours

タイムゾーンから時差を求めるコードの例(上:C#、下:VB)
タイムゾーンIDとして与えている「Pacific Standard Time」という文字列については、次で説明する。
GetUtcOffsetメソッドの結果を見ると、夏時間とそうでないときとでは時差が1時間異なっている。タイムゾーンの厄介なところである(現地時間で扱っていると2015年の11月1日には午前1時59分59秒の1秒後が午前1時になるのだ)。また、そのためにGetUtcOffsetメソッドの引数には、時差を知りたい時刻を与える必要があるのだ。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」を使用している。Visual Basic 2008以前の環境で試すには、適宜修正していただきたい。C#も同様に、C# 3.0(=VS 2008)から利用できるローカル型推論を使用している。

タイムゾーン情報を列挙するには?

 Windowsシステムが持っているタイムゾーン情報の全ては、TimeZoneInfoクラスのGetSystemTimeZones静的メソッドで取得できる(次のコードと画像)。結果はTimeZoneInfoオブジェクトのコレクションである。そのTimeZoneInfoオブジェクトのIdプロパティを、先に示したFindSystemTimeZoneById静的メソッドの引数などとして使うのである。以下の画面キャプチャではスクロールアウトしてしまっているが、上で示した「Pacific Standard Time」(PST)もタイムゾーンを示すIdであり、太平洋標準時(アメリカ西海岸で使われている標準時)を表している。

// システムに登録されているタイムゾーン情報を列挙する
var tzInfoList = TimeZoneInfo.GetSystemTimeZones();
foreach (var tzInfo in tzInfoList)
  Console.WriteLine("{0}: {1}",
                    tzInfo.DisplayName, tzInfo.Id);

' システムに登録されているタイムゾーン情報を列挙する
Dim tzInfoList = TimeZoneInfo.GetSystemTimeZones()
For Each tzInfo In tzInfoList
  Console.WriteLine("{0}: {1}",
                    tzInfo.DisplayName, tzInfo.Id)
Next

タイムゾーン情報を列挙するコードの例(上:C#、下:VB)
この出力結果は次の画像のようになる。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」と、Visual Basic 2010から利用できるようになった「暗黙の行連結」を使用している。Visual Basic 2010以前の環境で試すには、適宜修正していただきたい。C#も同様に、C# 3.0(=VS 2008)から利用できるローカル型推論を使用している。

タイムゾーン情報を列挙するコードの実行結果の例(一部) タイムゾーン情報を列挙するコードの実行結果の例(一部)
上のコードの実行結果の末尾付近を示す。
「(UTC+09:00) 大阪、札幌、東京」が日本標準時であり、そのタイムゾーンID文字列は「Tokyo Standard Time」である。
なお、この結果は2015年7月1日に実行したものであり、夏時間が終わった後では異なる結果になるはずである。

PCのタイムゾーン情報を取得するには?

 プログラムが実行されているPCに設定されているタイムゾーン情報は、TimeZoneInfoクラスのLocal静的プロパティで得られる(次のコード)。データ入力プログラムなどでは、これを使えば十分なことも多いだろう。

// 日本標準時のタイムゾーン情報を得る
var tzJst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");

// 動作しているPCに設定されているタイムゾーンを得る
var tzLocal = TimeZoneInfo.Local;

if (tzJst.Id == tzLocal.Id)
  Console.WriteLine("tzJst equals tzLocal, ID={0}", tzLocal.Id);
// 出力: tzJst equals tzLocal, ID=Tokyo Standard Time

' 日本標準時のタイムゾーン情報を得る
Dim tzJst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time")

' 動作しているPCに設定されているタイムゾーンを得る
Dim tzLocal = TimeZoneInfo.Local

If (tzJst.Id = tzLocal.Id) Then
  Console.WriteLine("tzJst equals tzLocal, ID={0}", tzLocal.Id)
End If
' 出力: tzJst equals tzLocal, ID=Tokyo Standard Time

PCのタイムゾーン情報を取得するコードの例(上:C#、下:VB)
このコードをタイムゾーンに日本標準時が設定してあるPCで実行すると、最後のコメントに示した結果が出力される。
なお、このVBのコードは、Visual Basic 2008から利用できるようになった「ローカル型の推論」を使用している。Visual Basic 2008以前の環境で試すには、適宜修正していただきたい。C#も同様に、C# 3.0(=VS 2008)から利用できるローカル型推論を使用している。

まとめ

 Windowsシステムが持っているタイムゾーンの情報を利用するには、TimeZoneInfoクラスを使う。夏時間の調整も自動的に行ってくれる。

 なお、Windowsランタイムアプリ/Windows 10のユニバーサルWindowsアプリではTimeZoneInfoクラスが使えない。その対策は「WinRT/Metro TIPS:夏時間を考慮して日時を変換するには?[Win 8/WP 8]」をご覧いただきたい。

利用可能バージョン: .NET Framework 3.5以降
カテゴリ: クラスライブラリ 処理対象:日付と時刻
使用ライブラリ: TimeZoneInfoクラス(System名前空間)
関連TIPS: DateTimeとDateTimeOffsetの違いとは?[C#、VB]
関連TIPS: UTC(世界協定時)を取得するには?[C#、VB]


■この記事と関連性の高い別の.NET TIPS


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。