I've been working with the DateTime
and TimeZoneInfo
classes and I ran into an interesting result with the following code:
var dstStart = new DateTime(2013, 3, 10, 2, 0, 0, DateTimeKind.Local);
var result = TimeZoneInfo.Local.IsDaylightSavingTime(dstStart);
The result of this is False
. I actually would have thought it would be True
(DST starts on March 10th at 2:00 AM)
Then I tried similar code using FindSystemTimeZoneById
instead:
var myTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var result = myTimeZone.IsDaylightSavingTime(dstStart);
The result of this is surprisingly True
.
I then checked to see that these objects are both representing the same time zone:
myTimeZone.Id == TimeZoneInfo.Local.Id // returns True (Both are "Eastern Standard Time")
My question is: why are these results different, and more importantly how can I make them the same?
My computer is definitely in the Eastern Standard Time
time zone
More information:
I resynced my computer's clock, and I ran a number of tests to compare the TimeZoneInfo
object that was returned by each of the above methods. Here is my test program
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)
);
I did a little bit of reflecting and I believe the inconsistency stems from how System.TimeZoneInfo+CachedData.GetCorrespondingKind(TimeZoneInfo timeZone)
returns DateTimeKind.Local
only in the case where timeZone == this.m_localTimeZone
(ie, when the argument was the same instance as the TimeZoneInfo.Local
property is based on).
In the case where you pass this other TimeZoneInfo
instance you got from TimeZoneInfo.FindSystemTimeZoneById
I expect that it returns DateTimeKind.Unspecified
.
This will (probably among other things) affect System.TimeZoneInfo.IsDaylightSavingTime(DateTime dateTime)
where, in the case where dateTime.Kind
is local, it does a conversion between essentially TimeZoneInfo.Local
and your TimeZoneInfo
instance and bases the conversion on what GetCorrespondingKind
says for the source and target timezones (the conversion returns the original datetime in the case where source and target are both local).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With