Reputation: 825
Today, I observed some strange behavior in the DateTime.Parse(String)
method when running on different servers. This can be observed in different online C# compilers.
My input in the yyyy-MM-ddTHH:mm:ssZ
format. Example: lets use 2020-02-12T16:57:36Z
which converted to ticks is: 637171234560000000
(converted using https://tickstodatetime.azurewebsites.net/)
This is the code I use for testing this behavior:
DateTime parsedDateTime = DateTime.Parse("2020-02-12T16:57:36Z");
Console.WriteLine(parsedDateTime + " " + parsedDateTime.Kind.ToString() + " " + parsedDateTime.Ticks);
On https://dotnetfiddle.net/akuyiI, it returns 02/12/2020 16:57:36 Local 637171234560000000
.
On https://rextester.com/XWH12209, it returns 12.02.2020 17:57:36 Local 637171270560000000
I understand that the DateTime is parsed into local timezone and displayed in local time, but why the number of ticks is also different between systems?
Upvotes: 4
Views: 4982
Reputation: 87
DateTime.ParseExact(DateTime, Format, DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite);
for example:
DateTime.ParseExact("06APR22/1605", "ddMMMyy/HHmm", DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite);
Upvotes: -1
Reputation: 1966
The answer is already in the question. The key point is in the output: 12.02.2020 17:57:36 Local 637171270560000000
The dateTime.kind shows what type of date it is? As the two website is most likely in two different places it shows two different times because .net has converted the given UTC time to their local time, which is reflected through DateTime.Kind.
If you instead run this
DateTime parsedDateTime = DateTime.Parse("2020-02-12T16:57:36Z").ToUniversalTime();
Console.WriteLine(parsedDateTime + " " + parsedDateTime.Kind.ToString() + " " + parsedDateTime.Ticks);
https://rextester.com/XWH12209
https://dotnetfiddle.net/o4XRFS
You will get the same date/time combination, because now it's not converted to local datetime but UTC instead.
For more clarification when I run your code on my local machine my output is:
12-Feb-20 10:57:36 PM Local 637171450560000000
Which basically means at the given UTC time it was 12-Feb-20 10:57:36 PM in my country.
Upvotes: 1
Reputation: 78135
A string in the yyyy-MM-ddTHH:mm:ssZ
format represents a date in UTC.
It is correctly parsed as such, but unfortunately, the resulting DateTime
value is DatetimeKind.Local
, and its value is adjusted accordingly to the time zone of the computer.
As stated in the comment in the beginning of the DateTime
source code file,
Starting from V2.0, DateTime also stored some context about its time zone in the form of a 3-state value representing Unspecified, Utc or Local. This is stored in the two top bits of the 64-bit numeric value with the remainder of the bits storing the tick count. This information is only used during time zone conversions and is not part of the identity of the DateTime. Thus, operations like Compare and Equals ignore this state. This is to stay compatible with earlier behavior and performance characteristics and to avoid forcing people into dealing with the effects of daylight savings. Note, that this has little effect on how the DateTime works except in a context where its specific time zone is needed, such as during conversions and some parsing and formatting cases.
Thus, the Ticks
property of a DatetimeKind.Local
date is relative to the local 12:00:00 midnight, January 1, 0001
, not to the UTC 12:00:00 midnight, January 1, 0001
.
This is documented in the remarks for the Ticks
property.
This also means that the two date instances obtained via this kind of DateTime.Parse
on different servers in different timezones, would compare as "unequal" even though they originate from the same string that describes the same UTC date. This is for backward compatibility.
In order to compare the ticks directly, you need to convert both dates to Kind.UTC
first.
Upvotes: 5
Reputation: 57573
A possible solution for different timezones in which date is parsed could be this:
DateTime parsedDateTime = DateTime.Parse(
"2020-02-12T16:57:36Z",
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal);
Upvotes: 1
Reputation: 127
It's about CultureInfo of the server you run on. DateTime.Parse has different overloads and parsing a datetime and also currency too, is depending on system's CultureInfo(language and region and etc.)
Upvotes: 1