C# DateTime.Parse("2012-09-30T23:00:00.0000000Z") 总是转换为 DateTimeKind.Local
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10029099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DateTime.Parse("2012-09-30T23:00:00.0000000Z") always converts to DateTimeKind.Local
提问by Giuseppe Romagnuolo
I want to parse a string that represent a DateTime in UTC format.
我想解析一个表示 UTC 格式的 DateTime 的字符串。
My string representation includes the Zulu time specification which should indicate that the string represent a UTC time.
我的字符串表示包括祖鲁时间规范,该规范应表明该字符串表示 UTC 时间。
var myDate = DateTime.Parse("2012-09-30T23:00:00.0000000Z");
From the above I would expect myDate.Kind to be DateTimeKind.Utc, instead it is DatetimeKind.Local.
从上面我希望 myDate.Kind 是 DateTimeKind.Utc,而不是 DatetimeKind.Local。
What am I doing wrong and how to Parse a string that represents a UTC time?
我在做什么错以及如何解析代表 UTC 时间的字符串?
Many thanks!
非常感谢!
采纳答案by Jon Skeet
I would use my Noda Timeproject personally. (Admittedly I'm biased as the author, but it would be cleaner...) But if you can't do that...
我会亲自使用我的Noda Time项目。(不可否认,我作为作者有偏见,但它会更干净......)但如果你不能这样做......
Either use DateTime.ParseExactspecifying the exact format you expect, and include DateTimeStyles.AssumeUniversaland DateTimeStyles.AdjustToUniversalin the parse code:
要么使用DateTime.ParseExact指定您期望的确切格式,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);
}
}
(Quite why it would adjust to local by default without AdjustToUniversalis beyond me, but never mind...)
(为什么它会默认调整到本地而AdjustToUniversal不是超出我的范围,但没关系......)
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):
编辑:只是为了扩大我对 mattytommo 建议的反对意见,我旨在证明它会丢失信息。到目前为止,我失败了——但以一种非常奇特的方式。看看这个 - 在欧洲/伦敦时区运行,时钟回到 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.
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.ConvertTimeToUtcstate
看起来有一个“有或没有 DST”标志存储在某处,但如果我能找出在哪里,我会感到震惊。TimeZoneInfo.ConvertTimeToUtc状态文档
If dateTimecorresponds to an ambiguous time, this method assumes that it is the standard time of the source time zone.
如果dateTime对应于不明确的时间,则此方法假定它是源时区的标准时间。
That doesn't appearto be the case here when converting local2...
这并不出现转换时,这里是如此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 differentUTC values, parses them with DateTime.Parse, then converts them back to UTC in two different ways.
所以这需要两个不同的UTC 值,用 解析它们DateTime.Parse,然后以两种不同的方式将它们转换回 UTC。
Results under .NET 3.5:
.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:
.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
回答by mattytommo
Use the TimeZoneInfoclass using the following:
使用TimeZoneInfo以下方法使用该类:
var myDate = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2012-09-30T23:00:00.0000000Z"));
回答by Simon Gillbee
As usual, Jon's answer is very comprehensive. That said, nobody has yet mentioned DateTimeStyles.RoundtripKind. If you want to convert a DateTime to a string and back to the same DateTime (including preserving the DateTime.Kindsetting), use the DateTimeStyles.RoundtripKindflag.
像往常一样,乔恩的回答非常全面。也就是说,还没有人提到DateTimeStyles.RoundtripKind。如果要将 DateTime 转换为字符串并返回到相同的 DateTime(包括保留DateTime.Kind设置),请使用该DateTimeStyles.RoundtripKind标志。
As Jon said, the correct thing to do is to use the "O" formatter when converting a DateTime object to a string. This preserves both the precision and timezone information. Again, as Jon said, use DateTime.ParseExactwhen converting back. But if you use DateTimeStyles.RoundtripKind, you always get back what you put in:
正如 Jon 所说,正确的做法是在将 DateTime 对象转换为字符串时使用“O”格式化程序。这保留了精度和时区信息。再次,正如乔恩所说,DateTime.ParseExact在转换回来时使用。但是如果你使用 DateTimeStyles.RoundtripKind,你总是会得到你输入的内容:
var now = DateTime.UtcNow;
var strNow = now.ToString("O");
var newNow = DateTime.ParseExact(strNow, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
In the above code, newNowis a exact same time as now, including the fact that it is UTC.
If run the same code except substitute DateTime.Nowfor DateTime.UtcNow, you'll get an exact copy of nowback as newNow, but this time as a local time.
在上面的代码中,newNow与 完全相同now,包括它是 UTC 的事实。如果运行不同的是用相同的代码DateTime.Now进行DateTime.UtcNow,你会得到的精确拷贝now回来的newNow这段时间,但作为本地时间。
For my purposes, this was the right thing since I wanted to make that sure that whatever was passed in and converted is converted back to the exact same thing.
就我而言,这是正确的事情,因为我想确保传入和转换的任何内容都转换回完全相同的内容。
回答by port443
You can use the following format for parser method: yyyy-MM-ddTHH:mm:ss.ffffffK
您可以对解析器方法使用以下格式: yyyy-MM-ddTHH:mm:ss.ffffffK
This shall properly process time zone information at the end (starting from .NET 2.0).
这将在最后正确处理时区信息(从 .NET 2.0 开始)。
RE: ISO 8601
回复:ISO 8601
回答by vandsh
Ran into a similar issue before and several hours (and pulled hairs) later ended up using DateTime.SpecifyKind:
之前遇到了类似的问题,几个小时后(和拉毛)最终使用DateTime.SpecifyKind:
DateTime.SpecifyKind(inputDate, DateTimeKind.Utc);
I believe someone also eluded to this in a comment above as well.
我相信有人也在上面的评论中回避了这一点。

