sashoalm sashoalm - 1 month ago 17
C# Question

Subtracting UTC and non-UTC DateTime in C#

I assumed that when subtracting 2 datetimes the framework will check their timezone and make the appropriate conversions.

I tested it with this code:

Console.WriteLine(DateTime.Now.ToUniversalTime() - DateTime.UtcNow.ToUniversalTime());
Console.WriteLine(DateTime.Now.ToUniversalTime() - DateTime.UtcNow);
Console.WriteLine(DateTime.Now - DateTime.UtcNow);


Output:

-00:00:00.0020002
-00:00:00.0020001
01:59:59.9989999


To my surprise,
DateTime.Now - DateTime.UtcNow
does not make the appropriate conversion automatically. At the same time,
DateTime.UtcNow
is the same as
DateTime.UtcNow.ToUniversalTime()
, so obviously there is some internal flag that indicates the time zone.

Is that correct, does that framework not perform the appropriate timezone conversion automatically, even if the information is already present? If so, is applying
ToUniversalTime()
safe for both UTC and non-UTC datetimes, i.e. an already UTC datetime will not be incorrectly corrected by
ToUniversalTime()
?

Answer

The type System.DateTime does not hold time zone information, only a .Kind property that specifies whether it is Local or UTC. But before .NET 2.0, there was not even a .Kind property.

When you subtract (or do other arithmetic, like == or >, on) two DateTime values, their "kinds" are not considered at all. Only the numbers of ticks are considered. This gives compatibility with .NET 1.1 when no kinds existed.

The functionality you ask for (and expect) is in the newer and richer type System.DateTimeOffset. In particular, if you do the subtraction DateTimeOffset.Now - DateTimeOffset.UtcNow you get the result you want. The DateTimeOffset structure does not have a local/UTC flag; instead, it holds the entire time zone, such as +02:00 in your area.

Comments