Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting DateTimes that are near DayLight Savings time?

I'm working on software that runs reports for GPS devices that are running 24/7/365. Part of the report output requires that we convert our stored database times (kept in Central Standard Time) to user timers (any requested time zone). Twice a year we run into an issue with DST when people run reports that start before and finish after the time change. It fails at one line:

return TimeZoneInfo.ConvertTime(dateToConvert, DatabaseTime, UserTime);

dateToConvert is a DateTime to be converted. DatabaseTime and UserTime are both TimeZoneInfo objects. I'm not doing anything tricky or complicated but DateTimes near the DST time change throw exceptions. Such as 3/10/2013 2:02:11 AM even though it's being "converted" from Central Time to Central Time.

What is the best method for handling DateTimes near DST time changes?

like image 502
Corey Ogburn Avatar asked Mar 18 '13 17:03

Corey Ogburn


4 Answers

You have garbage in your database, 3/10/2013 2:02:11 AM never existed. The minute after 1:59 AM that morning was 3:00 AM, the clock was moved by an hour. .NET is not going to put up with that junk date.

You will need to find out how that garbage timestamp ended up in your dbase. Clearly a conversion of a time from one timezone to another that disregards daylight savings rules, like active in one but not the other, is a highly likely source of that garbage. If you can't fix your dbase to use UTC then at least do it in your code. First going to UTC in the one timezone and then back to local time in the other. Use the TimeZoneInfo class, ConvertTimeFrom/ToUtc methods.

like image 175
Hans Passant Avatar answered Oct 08 '22 16:10

Hans Passant


I ran into this problem. I fixed it by adding a new GMT time column. This allowed the application to work with the original data and any fixes to work with GMT. Then I changed the application so that any code that was having problems with daylight savings would access this new column. Also, as time went on, I re-pointed any code that was used for calculation to this new column leaving the displays to work with the old column. It's not elegant, but it works and it is easy.

like image 38
Dave Avatar answered Oct 08 '22 14:10

Dave


Conversion should work properly as the time is not truly junk, as Hans stated, rather it is just non-adjusted (a term I just invented). 3/10/2013 2:02:11 AM CDT == 3/10/2013 8:02:11 AM UTC == 3/10/2013 3:02:11 AM CDT...they are ALL semantically equivalent. If you do not believe me, do the conversion at timeanddate.com and see they all equate (round to nearest 5 minutes for their calculator though). Whether .NET code will allow this semantic equivalence, I have not tried it because I am not in front of my dev box currently.

UPDATE #1:

Run the following code on a computer set to CST time zone:

using System;

namespace TimeZoneSample
{
    public static class Program
    {
        public static void Main()
        {
            DateTime t = DateTime.Parse("3/10/2013 2:02:11 AM");
            Console.WriteLine(t);
            Console.WriteLine(t.ToUniversalTime());
            Console.WriteLine(t.ToUniversalTime().ToLocalTime());
        }
    }
}

This yields the following console output:

3/10/2013 2:02:11 AM
3/10/2013 8:02:11 AM
3/10/2013 3:02:11 AM

Proof that my original explanation is correct. quod erat demonstrandum

like image 36
Daniel P. Bullington Avatar answered Oct 08 '22 16:10

Daniel P. Bullington


I would follow one of the other answers if that's at all possible - you want to fix this properly. If your time is incorrect during the fall transition it won't generate an exception, it's just going to randomly be an hour off.

There's a workaround to get you out of your current jam. Since it's only the missing hour during the spring that will cause the exception, you can catch the exception and add an hour into the time before repeating the conversion.

like image 1
Mark Ransom Avatar answered Oct 08 '22 16:10

Mark Ransom