I have an issue with the infamous daylight saving time.
I have a list of data points, one for each hour in a year. To check if all datapoints are present, I create a time iterator like this:
DateTime timeIterator = new DateTime(year, 1, 1, 0, 0, 0);
iterate it with
timeIterator = timeIterator.AddHours(1);
and check for each iteration if the point in time is present in the list.
The problem arises when it comes to daylight saving time. Im my example of year 2014, the clock is moved at the 30. of march from 0200 to 0300. So, after 0159 comes 0300. But DateTime.AddHours() completely ignores daylight saving. If timeIterator is at {30.03.2014 01:00:00} and I call AddHours(1) I get {30.03.2014 02:00:00} which obviously doesn't exist.
If I now test the list against this datapoint, it is (naturaly) not in the list and I throw a wrong "missing datapoint error".
How can I check, if my DateTime is a valid point in time?
Thanks in advance,
Frank
How can I check, if my DateTime is a valid point in time?
Don't check, ensure it. You can count hours in UTC and translate each point to local time for example.
DateTimeOffset timeIterator = new DateTimeOffset(new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Local));
timeIterator = timeIterator.AddHours(1);
timeIterator.LocalDateTime;
// assuming you have a TimeZoneInfo object, you can also get different local times:
TimeZoneInfo tzi = /* the timezone */;
TimeZoneInfo.ConvertTimeFromUtc(timeIterator.UtcDateTime, tzi);
However, as Damien_The_Unbeliever commented, this only solves one part of the problem, the program will no longer check for the existance of an invalid date. A different problem arises when your data are stored with local times. This means that the transition from DST to normal time will have two successive hours with the same local DateTime representation. In order to avoid this situation, the data must be stored with complete information (UTC or explicit offset) so that later comparison is possible.
Edit:
If you have a valid TimeZoneInfo
object for the timezone of your data and you don't want to switch over to DateTimeOffset
for some reason, you can also use the following functions:
TimeZoneInfo tzi = /* the timezone */;
DateTime timeIterator = /* the time */;
if (tzi.IsAmbiguousTime(timeIterator))
{
/* Expect multiple data entries */
}
if (tzi.IsInvalidTime(timeIterator))
{
/* Expect no data entries */
}