13

DateTimeおよびクラスを使用して作業しておりTimeZoneInfo、次のコードで興味深い結果に遭遇しました。

var dstStart = new DateTime(2013, 3, 10, 2, 0, 0, DateTimeKind.Local);
var result = TimeZoneInfo.Local.IsDaylightSavingTime(dstStart);

この結果は ですFalse。私は実際にそうなると思っていたでしょうTrue(DST は 3 月 10 日の午前 2 時に始まります)

FindSystemTimeZoneById次に、代わりに次のコードを使用して同様のコードを試しました。

var myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var result = myTimeZone.IsDaylightSavingTime(dstStart);

この結果は驚くべきことTrueです。

次に、これらのオブジェクトが両方とも同じタイム ゾーンを表していることを確認しました。

myTimeZone.Id == TimeZoneInfo.Local.Id // returns True (Both are "Eastern Standard Time")

私の質問は、なぜこれらの結果が異なるのか、さらに重要なことに、どうすればそれらを同じにできるのでしょうか?

私のコンピュータは間違いなくEastern Standard Timeタイムゾーンにある

詳しくは:

コンピューターの時計を再同期しTimeZoneInfo、上記の各メソッドによって返されたオブジェクトを比較するために、いくつかのテストを実行しました。ここに私のテストプログラムがあります

var timeZoneFromLookup = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var dstStart = new DateTime(2013, 3, 10, 2, 0, 0, DateTimeKind.Local);

// -- The following return true --

Console.WriteLine("Equal? {0}", TimeZoneInfo.Local.Equals(timeZoneFromLookup));

Console.WriteLine("Has Same Rules? {0}", TimeZoneInfo.Local.HasSameRules(timeZoneFromLookup));

Console.WriteLine("Same Id? {0}", TimeZoneInfo.Local.Id == timeZoneFromLookup.Id);

Console.WriteLine("Same Base UTC Offset? {0}", TimeZoneInfo.Local.BaseUtcOffset == timeZoneFromLookup.BaseUtcOffset);

Console.WriteLine("Same Daylight Name? {0}", TimeZoneInfo.Local.DaylightName == timeZoneFromLookup.DaylightName);

Console.WriteLine("Same Display Name? {0}", TimeZoneInfo.Local.DisplayName == timeZoneFromLookup.DisplayName);

Console.WriteLine("Same Standard Name? {0}", TimeZoneInfo.Local.StandardName == timeZoneFromLookup.StandardName);

Console.WriteLine("Same Support For DST? {0}", 
    TimeZoneInfo.Local.SupportsDaylightSavingTime == timeZoneFromLookup.SupportsDaylightSavingTime
);

Console.WriteLine("Same result as to whether date/time is ambiguous? {0}", 
    timeZoneFromLookup.IsAmbiguousTime(dstStart) == TimeZoneInfo.Local.IsAmbiguousTime(dstStart)
);

// -- The following return false --


Console.WriteLine("Same utc offset result? {0}", 
    timeZoneFromLookup.GetUtcOffset(dstStart) == TimeZoneInfo.Local.GetUtcOffset(dstStart)

);
Console.WriteLine("Same Conversion to UTC? {0}", 
    TimeZoneInfo.Local.GetUtcOffset(dstStart) == timeZoneFromLookup.GetUtcOffset(dstStart)
);

Console.WriteLine("Same result as to whether date/time is invalid? {0}", 
    timeZoneFromLookup.IsInvalidTime(dstStart) == TimeZoneInfo.Local.IsInvalidTime(dstStart)
);

Console.WriteLine("Same result as to whether date/time is DST? {0}", 
    timeZoneFromLookup.IsDaylightSavingTime(dstStart) == TimeZoneInfo.Local.IsDaylightSavingTime(dstStart)
);
4

2 に答える 2

8

私は少し反省しましたが、矛盾は howSystem.TimeZoneInfo+CachedData.GetCorrespondingKind(TimeZoneInfo timeZone)が返さDateTimeKind.Localれる場合にのみ(つまり、プロパティが基づいてtimeZone == this.m_localTimeZoneいるのと同じインスタンスが引数である場合) にのみ発生すると考えています。TimeZoneInfo.Local

TimeZoneInfo取得したこの他のインスタンスを渡す場合、 がTimeZoneInfo.FindSystemTimeZoneById返されると予想されますDateTimeKind.Unspecified

これは (おそらくとりわけ) System.TimeZoneInfo.IsDaylightSavingTime(DateTime dateTime)wheredateTime.Kindがローカルの場合に、本質的にインスタンスとインスタンスの間でTimeZoneInfo.Local変換TimeZoneInfoGetCorrespondingKind行い、ソースとターゲットのタイムゾーンの内容に基づいて変換を行う場所に影響します (この場合、変換は元の日時を返します)。ここで、ソースとターゲットは両方ともローカルです)。

于 2013-02-13T21:57:20.820 に答える
5

非ローカルを使用した場合の動作の違いは、 MSDN ドキュメントTimeZoneInfoで定義されています。

最初の結果はFalse、作成した DateTime オブジェクトが技術的にあいまいであるためです。EST ローカル タイム ゾーンには、2013 年 3 月 10 日の午前 2:00 はありません。

ドキュメントには、このIsDaylightSavingTime()メソッドは「TimeZoneInfo オブジェクトで表されるタイム ゾーンと dateTime パラメーターの Kind プロパティの関係によって影響を受ける」と記載されています。「備考」セクションの表は、考えられる各組み合わせの説明を示しています。

を明示的に呼び出してタイム ゾーンを指定する場合、FindSystemTimeZoneById最初に "Local Kind" DateTime 引数が Local から指定されたタイム ゾーンに変換されます。 このステップでは、あいまいな時間が正当な値に解決されます。

これをテストに追加してみてください:

var dstStart = new DateTime(2013, 3, 10, 2, 0, 0, DateTimeKind.Local);

dstStart = dstStart.ToUniversalTime();
dstStart = TimeZoneInfo.ConvertTime(dstStart, TimeZoneInfo.Utc, myTimeZone);

の最終的な値はdstStart3/10/2013 3:00:00 AM」になります (マシンがまだ EST にあると仮定します)。同じ種類の変換がIsDaylightSavingTime()、ローカルの kind パラメーター内で発生しています。これは、なぜ が返されるのかを示していますTrue

ここで本当に驚いたのは、どちらの場合もIsDaylightSavingTime()メソッドが an を発生させないことです。ドキュメントには、種類が である無効なパラメーターをArgumentException指定すると例外がスローされると記載されていますが、明らかにこれは発生しません。DateTimeDateTimeKind.Local

編集:

クラスのソース コードとコメントを調べた結果、このメソッドは例外をスローするためTimeZoneInfoのものではないという結論に達しました。IsDaylightSavingTime()これはドキュメントの間違いです。

于 2013-05-08T04:52:14.893 に答える