ToUniversalTime()。AddYears()。ToLocalTime()を呼び出すうるう年バグ?
質問
.NETの DateTime
処理、具体的には ToLocalTime()
の処理でうるう年に遭遇しました。問題を再現するコードをいくつか示します(私は太平洋時間帯にいます):
DateTime dtStartLocal = DateTime.Parse("2009-02-28T23:00:00.0-08:00");
DateTime dtEndLocal = dtStartLocal.AddYears(3);
DateTime dtStartUtc = dtStartLocal.ToUniversalTime();
DateTime dtEndUtc = dtStartUtc.AddYears(3);
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();
DateTime dtStartLocal2 = dtStartUtc.ToLocalTime();
Console.WriteLine("START: 1={0}, 2={0}", dtStartLocal, dtStartLocal2);
Console.WriteLine("END : 1={0}, 2={1}", dtEndLocal, dtEndLocal2);
Console.ReadLine();
出力は次のとおりです。
START:1 = 2/28/2009 11:00:00 PM、2 = 2/28/2009 11:00:00 PM
終了:1 = 2/28/2012 11:00:00 PM、2 = 2/29/2012 11:00:00 PM
ToUniversalTime()。AddYears(3).ToLocalTime()を実行した変数が AddYears(3)
とは異なることに注意してください。1日先です。
これに遭遇した人はいますか?これが予想される場合、誰かがその背後にあるロジックを説明できますか?
注:はい、最善のアプローチはUTC間で完全に動作し、それらの間でフリップフロップを行わないことです。これは私に影響を与えるものではなく、私が遭遇した特異性です。基本的に、 AddYears()
の仕組みを誤解していたので、なぜそれが実行されているのかがわかります(以下の選択した回答を参照)。
解決
これは正しく機能していると思います。
DateTime dtStartUtc = dtStartLocal.ToUniversalTime();
PSTはUTC-8です。したがって、これは時刻を2009年3月1日07:00:00に変換します。
DateTime dtEndUtc = dtStartUtc.AddYears(3);
これにより、前の時間に3年が追加され、2012年3月1日の07:00:00に置かれます。
DateTime dtEndLocal2 = dtEndUtc.ToLocalTime();
これにより、終了時刻がPSTに変換されます。PSTは2012年2月29日11:00:00です。
これは、ローカル時間とUTC時間の間の変換の副作用にすぎないと思います。
他のヒント
タイムゾーン/補正係数を印刷します。 .ToUniversialTime()を実行すると、基本的に元の時刻(「-08:00」)から8時間が加算され、2月28日の23:00時間から翌日の11:00に追加されます。したがって、3年を追加すると、29日の午前11:00になります。 2年をやっていたら、それは3月1日だったでしょう。うるう年とは関係ありません。
私が知る限り、この動作は間違っていません。現地時間をUTCに変換すると、事実上それを翌日にプッシュします。 3月1日3年を追加すると、3月1日のままになります。それを現地時間に変換し、前日にロールバックします。2012年はうるう年であるため、2月29日です。