Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse date time c# with correct timezone and kind

I have a datetime in database which I read using SqlDataReader and then cast it to (DateTime). After the cast its Kind property is DateTimeKind.Unspecified.

Then I have another string which I read from some other source. Its format is like this 2016-01-20T22:20:29.055Z. I do DateTime.Parse("2016-01-20T22:20:29.055Z") and its Kind property is DateTimeKind.Local.

How do I properly parse the both date times for comparison? Do I need to use DateTimeOffsets? How should I parse them?

Thanks

like image 976
Shikasta_Kashti Avatar asked Jan 20 '16 22:01

Shikasta_Kashti


People also ask

What is DateTime parsing?

Parse converts the datetime string into a DateTime . It automatically tries to figure out the datetime format. The DateTime. ParseExact method converts the specified string representation of a datetime to a DateTime . The datetime string format must match the specified format exactly; otherwise an exception is thrown.

What is ParseExact C#?

ParseExact(String, String, IFormatProvider) Converts the specified string representation of a date and time to its DateTime equivalent using the specified format and culture-specific format information. The format of the string representation must match the specified format exactly.

How do I convert a string to a date?

Using strptime() , date and time in string format can be converted to datetime type. The first parameter is the string and the second is the date time format specifier. One advantage of converting to date format is one can select the month or date or time individually.


2 Answers

Because SQLReader cannot reasonably infer a DateTimeKind, it leaves it as unspecified. You'll want to use DateTime.SpecifyKind to change the DateTimeKind on your output from the SQLReader to the appropriate value. This works ok if you are only dealing with UTC and one consistent local time zone; otherwise, you really should be using DateTimeOffset in both your code and the SQL Database.

The string "2016-01-20T22:20:29.055Z" is ISO 8601 compliant and is a UTC date; however, DateTime.Parse with only 1 argument can end up performing a conversion to local time. Per the documentation:

Generally, the Parse method returns a DateTime object whose Kind property is DateTimeKind.Unspecified. However, the Parse method may also perform time zone conversion and set the value of the Kind property differently, depending on the values of the s and styles parameters:

  • If s contains time zone information, the date and time is converted to the time in the local time zone and the Kind is DateTimeKind.Local.
  • If s contains time zone information, and styles includes the AdjustToUniversalflag, the date and time is converted to Coordinated Universal Time (UTC) and the Kind is DateTimeKind.Utc.
  • If s contains the Z or GMT time zone designator, and styles includes the RoundtripKind flag, the date and time are interpreted as UTC and the Kind is DateTimeKind.Utc.

Also see UTC gotchas in .NET and SQL Server in Derek Fowler's blog for additional coverage on the topic.

like image 101
JamieSee Avatar answered Nov 08 '22 03:11

JamieSee


In your second example, 2016-01-20T22:20:29.055Z has timezone information provided with it; the 'Z' at the end indicates that the timestamp is intended for Coordinated Universal Time (UTC). However, DateTime.Parse() will default its conversion using DateTimeKind.Local unless a specific timezone is specified. You can use DateTime.ParseExact to be more specific.

As to why the datetime values in your database are coming out as Unspecified, that's likely because they contain no timezone indication at all. Check to see if your database values specify timezone information, either by using 'Z' at the end or specifying an exact timezone, such as 2016-01-20T22:20:29.055-07:00 (UTC-7).

like image 36
Chase Avatar answered Nov 08 '22 02:11

Chase