Search code examples
c#winformsdatetimetimezoneargumentexception

DateTime error during time change to daylight saving time


I have to plot a dataset over time which I calculate from a short array. This works but when it comes to converting to the correct time zone it throws an exception:

System.ArgumentException: "The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid. Parameter name: dateTime"

The problem is that the dataset was recorded during time shift to daylight saving time, so there is a gap between 2 and 3 AM. From 2 AM on, the times are invalid because they simply do not exist. But when I try to include an if statement to prove on invalid times it does not help because the bool "isvalid" is always false. I don't get why the bool stays false although a few lines later it throws an exception that this DateTime is invalid, so what can I do? Thanks for helping!

Additional information: The Kind of date_0 is Local.

DateTime date_0;             //equals {29.03.2020 02:00:00} which is invalid 
TimeZoneInfo tzf = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");                       
bool isInvalid = tzf.IsInvalidTime(date_0);
if (isInvalid)
    {
          //do something (but this is never reached)
    }
DateTime dt = TimeZoneInfo.ConvertTime(date_0, tzf);   //here the exception is thrown
var isSum = tzf.IsDaylightSavingTime(dt);
if (isSum) date_0 = date_0.AddHours(1);

Solution

Thanks for the helpful comments. The problem was that the Kind of date_0 was different to the TimeZoneInfo tzf. I resolved it by just changing tzf to Local which corresponds to date_0. Now the invalid DateTime is recognized and further steps can be done.

TimeZoneInfo tzf = TimeZoneInfo.Local;
if(tzf.IsInvalidTime(date_0))
   {
         // ...
   } 

Solution

  • I assume that your DateTime has a Kind of Unspecified. From the online documentation IsInvalidTime would then assume "dateTime is the time of the TimeZoneInfo object and determines whether it is invalid".

    Whereas ConvertTime says "Assumed to be Local. Converts the local time to the time in destinationTimeZone."

    So if your Local timezone is not the same as your TimeZoneInfo, the result will be surprising.

    If your DateTime.Kind is Local, but your TimeZoneInfo is not local then the documentation suggests that IsInvalidTime will "Converts dateTime to the time of the TimeZoneInfo object and returns false." Which is what the source code does. What's the point of a function that always returns false?

    Since it looks like you are processing datetimes that are neither Local nor UTC, you should convert to DateTimeOffset, or just convert everything to UTC.

    date_0 = DateTime.SpecifyKind(date_0, DateTimeKind.Unspecified);
    if (tzf.IsInvalidTime(date_0)){
       // ...
    }
    var dto = new DateTimeOffset(date_0, tzf.GetUtcOffset(date_0));