はじめに
日本にサマータイムが導入されるかもしれないそうなので、.NETにおける日本標準時の仕様をチェックした。
以下は、東京標準時に設定されているWindows 10のPCでC#インタラクティブを実行した結果になる。
日本標準時の仕様
現在のタイムゾーン情報を取得するには以下のようにする。
TimeZoneInfo.Local
各プロパティは以下のようになる。
> TimeZoneInfo.Local.Id
"Tokyo Standard Time"
> TimeZoneInfo.Local.StandardName
"東京 (標準時)"
> TimeZoneInfo.Local.DisplayName
"(UTC+09:00) 大阪、札幌、東京"
"Japan Standard Time"ではなくて、"Tokyo Standard Time"である。
日本がひとつのタイムゾーンしかもたないという前提を極力排した名前ということだろう。桃岩時間のサポートが考慮されていると考えると胸が高なる。
> TimeZoneInfo.Local.SupportsDaylightSavingTime
false
> TimeZoneInfo.Local.GetAdjustmentRules()
TimeZoneInfo.AdjustmentRule[0] { }
タイムゾーン調整ルールは存在しない。
この調整ルールはサマータイムの規則のことなので、日本はサマータイムが導入されていないということになる。
いや、それぞれのルールは適用される開始日と終了日を持つので、より正しくは「.NETの世界」ではサマータイムが導入されたことがない、その予定もないということになる。
これは、日本では1948年から1951年にかけてサマータイムが導入されていたという事実に反する。
そのため、
> var date = new DateTimeOffset(1948, 5, 2, 9, 0, 0, TimeSpan.FromHours(9));
> TimeZoneInfo.ConvertTime(date, TimeZoneInfo.Local)
[1948/05/02 9:00:00 +09:00]
となる。
1948年5月2日はサマータイム初日であるので、歴史的に正しい処理系であれば
[1948/05/02 10:00:00 +10:00]
となるはずであるが、.NETの仕様ではこのようになっている。直感的でわかりやすいと言ってもいいし、歴史的に正しくないという言い方もできる。
歴史的に正しい結果を返す環境として、PHPがある。
http://d.hatena.ne.jp/hnw/20101223
PHPが元にしているtz databaseを使用する処理系では同じ結果になるのだろう。
なお、夏時間の表示名だけは用意されている。
> TimeZoneInfo.Local.DaylightName
"東京 (夏時間)"
サマータイム導入タイムゾーンではどうなっているか
では、サマータイムが導入されるとどういうことになるのだろうか。
例として、太平洋標準時でおこなった結果が以下のとおりだ。
> var pst = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
> pst.Id
"Pacific Standard Time"
> pst.StandardName
"太平洋標準時"
> pst.DisplayName
"(UTC-08:00) 太平洋標準時 (米国およびカナダ)"
> pst.DaylightName
"太平洋夏時間"
> var date1 = new DateTimeOffset(2018, 1, 1, 0, 0, 0, TimeSpan.FromHours(-8));
> TimeZoneInfo.ConvertTime(date1, pst)
[2018/01/01 0:00:00 -08:00]
> var date2 = new DateTimeOffset(2018, 6, 1, 0, 0, 0, TimeSpan.FromHours(-8));
> TimeZoneInfo.ConvertTime(date2, pst)
[2018/06/01 1:00:00 -07:00]
00:00:00という同じ時刻を指定しても、1月と6月とでローカルの時刻やオフセットの値が変わるのがわかる。
> pst.SupportsDaylightSavingTime
true
> pst.GetAdjustmentRules()
TimeZoneInfo.AdjustmentRule[2] { TimeZoneInfo.AdjustmentRule { DateEnd=[2006/12/31 0:00:00], DateStart=[0001/01/01 0:00:00], DaylightDelta=[01:00:00], DaylightTransitionEnd=[System.TimeZoneInfo+TransitionTime], DaylightTransitionStart=[System.TimeZoneInfo+TransitionTime] }, TimeZoneInfo.AdjustmentRule { DateEnd=[9999/12/31 0:00:00], DateStart=[2007/01/01 0:00:00], DaylightDelta=[01:00:00], DaylightTransitionEnd=[System.TimeZoneInfo+TransitionTime], DaylightTransitionStart=[System.TimeZoneInfo+TransitionTime] } }
もちろん、タイムゾーンに夏時間規則があると返す。
GetAdjustmentRule()
が返す配列の要素がふたつあるのは、サマータイムの扱いが2007年を区切りに変化しているからだ。
https://ja.wikipedia.org/wiki/%E5%A4%AA%E5%B9%B3%E6%B4%8B%E5%A4%8F%E6%99%82%E9%96%93
2006年までは、4月の第1日曜日午前2時から10月の最終日曜日午前2時までの期間の適用であったが、2007年以降は、3月の第2日曜日午前2時から11月の第1日曜日午前2時までの期間の適用に変更された。
2006年末までの調整ルールと2007年頭からの調整ルールとで、合計ふたつということになる。