2

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))
   {
         // ...
   } 
  • _"true if dateTime is invalid; otherwise, false."_ - [docs](https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.isinvalidtime?view=netcore-3.1) So your `isvalid` variable is inverted. It should actually be `isInValid` or `isvalid = !tzf.IsInvalidTime(date_0);` – Fildor Jul 30 '20 at 06:29
  • See also [Coding Best Practices Using DateTime in the .NET Framework](https://learn.microsoft.com/en-us/previous-versions/dotnet/articles/ms973825(v=msdn.10)?redirectedfrom=MSDN) – Fildor Jul 30 '20 at 06:38
  • What Kind does date_0 have? If you aren't dealing with UTC & local time exclusively, you should probably be using `DateTimeOffset`. – Jeremy Lakeman Jul 30 '20 at 06:39
  • 1
    @Fildor: You're right. I changed the variable name for better understanding – Chris_29863 Jul 30 '20 at 06:53
  • @JeremyLakeman: The kind of date_0 is Local – Chris_29863 Jul 30 '20 at 06:54
  • @Chris_29863 please consider adding that info to the question. It is quite essential and people tend to fly over comments, easily. – Fildor Jul 30 '20 at 06:56

1 Answers1

3

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));
Jeremy Lakeman
  • 9,515
  • 25
  • 29