Reputation: 677
I am surprised by the behaviour of TimeZoneInfo.IsValidTime() as it doesn't work as I expected with an invalid DateTime set as DateTimeKind.Local
[Fact]
public void DateTimeInvalidForTimeZone()
{
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
var testTimeUnspec = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Unspecified);
var testTimeLocal = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Local);
var testTimeUtc = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Utc);
Assert.False(timeZone.IsInvalidTime(testTimeUtc)); //as anticipated - UTC so cannot be invalid
Assert.True(timeZone.IsInvalidTime(testTimeUnspec)); //as anticipated - the time is invalid
Assert.False(timeZone.IsInvalidTime(testTimeLocal)); //unexpected - the time is invalid
}
Note: Central European Standard Time transitions to daylight saving on 29 March 2020 at 02:00AM so the time sequence in terms of local time is 01:59:58, 01:59:59, 03:00:00, 03:00:01. Accordingly all local times between 02:00:00 and 02:59:59 are invalid.
The Microsoft Documentation explains:
This suggests that DateTime objects that are DateTimeKind.Local will be always be valid which is not what I expect or want. Can anyone explain the logic behind Microsoft's implementation? Yet another reason to consider Nodatime?
Upvotes: 2
Views: 727
Reputation: 241808
As you pointed out, the docs for TimeZoneInfo.IsInvalidTime
explain that returning false
is the documented behavior when the TimeZoneInfo
is not the local time zone, and is correct regardless of whether the time is valid in either the local time zone or the one belonging to the TimeZoneInfo
object. Indeed, the implementation simply returns false
in this case.
If you want to know if local times are valid or not, then you need to use the TimeZoneInfo.Local
time zone, rather than one obtained by id. It doesn't matter if that named time zone happens to be the local one or not, you need to be explicitly working with TimeZoneInfo.Local
if you're testing DateTimeKind.Local
values.
In other words, if your computer's system local time zone is indeed "Central European Standard Time"
(assuming "Adjust for daylight saving time automatically" is turned on) then the following will return True
as expected.
TimeZoneInfo.Local.IsInvalidTime(new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Local))
Upvotes: 1