Datetime.Parse("2012-09-30T23:00:00.0000000Z") Always Converts to Datetimekind.Local

DateTime.Parse(2012-09-30T23:00:00.0000000Z) always converts to DateTimeKind.Local

I would use my Noda Time project personally. (Admittedly I'm biased as the author, but it would be cleaner...) But if you can't do that...

Either use DateTime.ParseExact specifying the exact format you expect, and include DateTimeStyles.AssumeUniversal and DateTimeStyles.AdjustToUniversal in the parse code:

using System;
using System.Globalization;

class Test
{
static void Main()
{
var date = DateTime.ParseExact("2012-09-30T23:00:00.0000000Z",
"yyyy-MM-dd'T'HH:mm:ss.fffffff'Z'",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal);
Console.WriteLine(date);
Console.WriteLine(date.Kind);
}
}

(Quite why it would adjust to local by default without AdjustToUniversal is beyond me, but never mind...)

EDIT: Just to expand on my objections to mattytommo's suggestion, I aimed to prove that it would lose information. I've failed so far - but in a very peculiar way. Have a look at this - running in the Europe/London time zone, where the clocks go back on October 28th in 2012, at 2am local time (1am UTC):

DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");
Console.WriteLine(local1 == local2); // True

DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
Console.WriteLine(utc1 == utc2); // False. Hmm.

It looks like there's a "with or without DST" flag being stored somewhere, but I'll be blowed if I can work out where. The docs for TimeZoneInfo.ConvertTimeToUtc state

If dateTime corresponds to an ambiguous time, this method assumes that it is the standard time of the source time zone.

That doesn't appear to be the case here when converting local2...

EDIT: Okay, it gets even stranger - it depends which version of the framework you're using. Consider this program:

using System;
using System.Globalization;

class Test
{
static void Main()
{
DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");

DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
Console.WriteLine(utc1);
Console.WriteLine(utc2);

DateTime utc3 = local1.ToUniversalTime();
DateTime utc4 = local2.ToUniversalTime();
Console.WriteLine(utc3);
Console.WriteLine(utc4);
}
}

So this takes two different UTC values, parses them with DateTime.Parse, then converts them back to UTC in two different ways.

Results under .NET 3.5:

28/10/2012 01:30:00 // Look - we've lost information
28/10/2012 01:30:00
28/10/2012 00:30:00 // But ToUniversalTime() seems okay...
28/10/2012 01:30:00

Results under .NET 4.5 beta:

28/10/2012 00:30:00 // It's okay!
28/10/2012 01:30:00
28/10/2012 00:30:00
28/10/2012 01:30:00

How to convert string with a T and Z to DateTime

You could try something like this:

var dateString = "20150521T205510Z";

var date = DateTime.ParseExact(dateString,
"yyyyMMdd'T'HHmmss'Z'",
CultureInfo.InvariantCulture);

I referenced the answer from: DateTime.Parse("2012-09-30T23:00:00.0000000Z") always converts to DateTimeKind.Local

Time.parse and DateTime.parse returns different results

There is no timezone information in the input String. DateTime.parse therefore assumes UTC. Time.parse assumes local time, and I guess you're in UTC+2.

>> time = "13:30:0"
=> "13:30:0"
>> DateTime.parse(time).to_s
=> "2013-10-13T13:30:00+00:00"
>> Time.parse(time).to_s
=> "2013-10-13 13:30:00 +0200"

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

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.

DateTime.ParseExact with string in format 2012-08-17T04:39:51.215Z

string stringdate = "2012-09-14T04:42:25.117Z";
DateTime date = new DateTime();
DateTime.TryParse(stringdate,out date);
MessageBox.Show(date.ToShortDateString());

eg:

MessageBox.Show(date.ToLocalTime().ToString());

Sample Image

Edit:

In the MSDN DateTime.TryParseExact Method:

The string parameter is parsed using default values. No white space
other than that present in format is allowed. If string lacks a date
component, the date of the returned DateTime value is set to 1/1/0001.

I see you are suppplying the Date component. My only guess is that I'm in Australia and it works and we use DD-MM-YYYY and in the US its MM-DD-YYYY. Perhaps flip it around and see if that works, eg:

"2012-17-08T04:39:52.878Z"

c# convert string to date - what kind of format is this?

This is the format that applies to your string, although it is not a valid string according to the ISO 8601 standard:

var date = DateTime.ParseExact("2014-11-03 08:44:00:082467 Z",
"yyyy-MM-dd' 'HH:mm:ss:ffffff' Z'",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal |
DateTimeStyles.AdjustToUniversal);

Dotnetfiddle



Related Topics



Leave a reply



Submit