Dongminator
Dongminator

Reputation: 825

C# DateTime.Parse(String) returns different value in different system

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

Answers (5)

Hossein Kohzadi
Hossein Kohzadi

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

SZT
SZT

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

GSerg
GSerg

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

Marco
Marco

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

Ozan Topal
Ozan Topal

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

Related Questions