Date and time calculations done with local times can produce erroneous results. For example, consider this code, which adds one day to March 9, 2013 at 2:01 AM.
DateTime localStart = new DateTime(2013, 03, 09, 02, 01, 00); // 2:00 AM on 03/09/2013
DateTime localResult = localStart.AddDays(1.0);
Console.WriteLine("Local start date/time = {0}", localStart);
Console.WriteLine("Result of AddDays(1.0) = {0}", localResult);
The result will be March 10, 2013 2:01 AM. That seems right, but in my local time zone it’s incorrect. 2:01 AM never existed on that date. When 2:00 AM rolled around, the clock was zipped forward an hour for the annual Daylight Saving Time “spring ahead” adjustment.
The documentation for DateTime
says:
Conversion operations between time zones (such as between UTC and local time, or between one time zone and another) take daylight saving time into account, but arithmetic and comparison operations do not.
The same thing happens with DateTimeOffset
.
If you want to do date and time calculations, you should convert the values to UTC first. Perform your calculations and then convert the results back to local time. For example, this code produces the correct result:
DateTime utcStart = new DateTime(2013, 03, 09, 02, 01, 00).ToUniversalTime();
DateTime utcResult = utcStart.AddDays(1.0);
Console.WriteLine("UTC start date/time = {0}", utcStart);
Console.WriteLine("Result of AddDays(1.0) = {0}", utcResult);
Console.WriteLine();
Console.WriteLine("UTC result converted to local time = {0}", utcResult.ToLocalTime());
This is just one of the many problems that can occur when working with dates and times. I’ve found through hard experience that if you’re storing dates and times, you should store them as UTC. And when a user inputs a date and time, you should convert it to UTC as soon as possible. All datetime calculations and all datetime persistence should be UTC.
You could, if you wanted to keep track of where a particular data item was collected, persist times as DateTimeOffset
, with the proper offset applied. Remember, though, to convert to UTC before doing any calculations.
Whichever you choose, be consistent. Otherwise you’re going to lose information and produce erroneous results.