DateTime.Parse(“2012-09-30T23:00:00.0000000Z”)总是转换为DateTimeKind.Local

我想分析一个代表UTC格式的date时间的string。

我的string表示包括Zulu时间规范,它应该表明该string表示UTC时间。

var myDate = DateTime.Parse("2012-09-30T23:00:00.0000000Z"); 

从上面我会期望myDate.Kind是DateTimeKind.Utc,而不是DatetimeKind.Local。

我做错了什么,以及如何parsing表示UTC时间的string?

非常感谢!

我会亲自使用野田时间 ,但如果你不能这样做…

使用DateTime.ParseExact指定您期望的确切格式,并在parsing代码中包含DateTimeStyles.AssumeUniversalDateTimeStyles.AdjustToUniversal

 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); } } 

(相当为什么它会默认调整到本地,没有AdjustToUniversal超出了我,但没关系…)

编辑:只是为了扩大我对mattytommo的build议的反对意见,我的目的是certificate它会失去信息。 我迄今为止失败了 – 但是以一种非常奇特的方式。 看看这个 – 在欧洲/伦敦时区,时间在2012年10月28日,当地时间凌晨2点(UTC凌晨1点):

 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. 

看起来有一个“有或没有DST”标志存储在某处 ,但如果我可以在哪里解决,我会被炸掉。 TimeZoneInfo.ConvertTimeToUtc状态的文档

如果dateTime对应于模糊时间,则此方法假定它是源时区的标准时间。

当转换local2时,这似乎不是这种情况…

编辑:好吧,它变得更陌生 – 这取决于你使用的框架的版本。 考虑这个程序:

 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); } } 

所以这需要两个不同的 UTC值,用DateTime.Parseparsing它们,然后用两种不同的方法将它们转换回UTC。

在.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 

.NET 4.5testing版下的结果:

 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 

像往常一样,乔恩的回答非常全面。 也就是说,没有人提到DateTimeStyles.RoundtripKind 。 如果要将DateTime转换为string并返回到相同的DateTime(包括保留DateTime.Kind设置),请使用DateTimeStyles.RoundtripKind标志。

正如Jon所说,正确的做法是在将DateTime对象转换为string时使用“O”格式化程序。 这保留了精度和时区信息。 再次,如Jon所说,转换回来时使用DateTime.ParseExact 。 但是,如果你使用DateTimeStyles.RoundtripKind,你总是会回来你把什么:

 var now = DateTime.UtcNow; var strNow = now.ToString("O"); var newNow = DateTime.ParseExact(strNow, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); 

在上面的代码中, newNownow完全相同,包括UTC。 如果运行相同的代码,除了将DateTime.Nowreplace为DateTime.UtcNow ,您将得到一个nownewNow的精确副本,但这次是作为当地时间。

为了我的目的,这是正确的,因为我想确保传入和转换的东西都转换回完全一样的东西。

使用以下的TimeZoneInfo类:

 var myDate = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2012-09-30T23:00:00.0000000Z")); 

您可以使用以下格式的parsing器方法: yyyy-MM-ddTHH:mm:ss.ffffffK

这应该最后处理时区信息( 从.NET 2.0开始 )。

RE: ISO 8601

之前和几个小时(并拉动头发)后类似的问题后来结束了使用DateTime.SpecifyKind :

 DateTime.SpecifyKind(inputDate, DateTimeKind.Utc); 

我相信有人在上面的评论中也避开了这个。