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.AssumeUniversal
和DateTimeStyles.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.Parse
parsing它们,然后用两种不同的方法将它们转换回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);
在上面的代码中, newNow
与now
完全相同,包括UTC。 如果运行相同的代码,除了将DateTime.Now
replace为DateTime.UtcNow
,您将得到一个now
为newNow
的精确副本,但这次是作为当地时间。
为了我的目的,这是正确的,因为我想确保传入和转换的东西都转换回完全一样的东西。
使用以下的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);
我相信有人在上面的评论中也避开了这个。