This (LINQPad snippet):
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump();
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump();
Returns:
2016-01-08T09:05:04-07:00 // Expected
2016-01-08T16:05:04-07:00 // Not what I expected
Given that the 2nd result is universal time, I expected it to return 2016-01-08T16:05:04-00:00
(timezone offset of zero).
Am I missing something or is this a bug?
A DateTime value defines a particular date and time. It includes a Kind property that provides limited information about the time zone to which that date and time belongs.
The main difference between it and the simpler DateTime type we all know and love is that it includes a time zone offset from UTC. Thus, it's always clear when looking at a DateTimeOffset what time is meant, whether UTC or local.
Use DateTime. UtcNow when you want to store dates or use them for later calculations that way (in a client-server model) your calculations don't become confused by clients in different time zones from your server or from each other.
The DateTimeOffset structure includes a DateTime value, together with an Offset property that defines the difference between the current DateTimeOffset instance's date and time and Coordinated Universal Time (UTC).
I wanna combine Gusman's and Evan's comments and create some arguments against them if they let me. Let's take step by step..
Should
DateTime.UtcNow
have a timezone offset?
No matter what Kind
it has (Local, Utc or Unspecified), a DateTime
instance does not keep any UTC offset value. Period.
First of all, let's take a look at the The "zzz"
format specifier documentation;
With DateTime values, the "zzz" custom format specifier represents the signed offset of the local operating system's time zone from UTC, measured in hours and minutes. It does not reflect the value of an instance's DateTime.Kind property. For this reason, the "zzz" format specifier is not recommended for use with DateTime values.
Based on first two bold sentences, both result generated by LINQPad is totally expected. You can get the same results (expect date and time parts of course) in Visual Studio as well.
Just run this code as "Start Without Debugging" (Ctrl + F5)
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));
Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz"));
But what about when you run it as "Start Debugging" with (F5)?
There are two option in such a case which depends on your DateTimeInvalidLocalFormat
in Managed Debugging Assistants is ticked or not. This sections is on the Debug
menu, then click Exceptions
.
If this option is ticked, you get an exception and it says;
A
UTC
DateTime is being converted to text in a format that is only correct for local times. This can happen when callingDateTime.ToString
using the'z'
format specifier, which will include a local time zone offset in the output. In that case, either use the'Z'
format specifier, which designates a UTC time, or use the'o'
format string, which is the recommended way to persist a DateTime in text.
If this option is not ticked, you won't get any message and the result will be the same as LINQPad.
Given that the 2nd result is universal time, I expected it to return
2016-01-08T16:05:04-00:00
(timezone offset of zero).
As I explained, zzz
format specifier does not behave like that for any DateTime
instance.
But it behaves differently for a DateTimeOffset
instance which is documented as;
With
DateTimeOffset
values, this format specifier represents the DateTimeOffset value'sOffset
from UTC in hours.
And DateTimeOffset.Now
and DateTimeOffset.UtcNow
are perfectly fits your expectation no matter you run in LINQPad or Visual Studio since they are documented as;
Now
A DateTimeOffset object whose date and time is the current local time and whose offset is the local time zone's offset from Coordinated Universal Time (UTC).
UtcNow
An object whose date and time is the current Coordinated Universal Time (UTC) and whose offset is
TimeSpan.Zero
.
Console.WriteLine(DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));
Console.WriteLine(DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz"));
would generate
2016-01-08T09:05:04-07:00
2016-01-08T16:05:04-00:00
Tl;dr I think this is not a bug. LINQPad generates the right results exactly what it should be. In Visual Studio, you might get an exception if that option is ticked or not in debugging mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With