DateTime.Parse(“2012-09-30T23:00 0.0000000000 Z”)总是转换为DateTi
本文关键字:转换 DateTi 0000000000 Parse 2012-09-30T23 DateTime | 更新日期: 2023-09-27 18:30:02
我想解析一个以UTC格式表示DateTime的字符串。
我的字符串表示包括祖鲁时间规范,它应该指示字符串表示UTC时间。
var myDate = DateTime.Parse("2012-09-30T23:00:00.0000000Z");
根据以上内容,我希望我的Date.Kind是DateTimeKind.Utc,而不是DateTimeKind.Local.
我做错了什么?如何解析表示UTC时间的字符串?
非常感谢!
我会亲自使用我的Noda Time项目。(诚然,作为作者,我有偏见,但它会更干净…)但如果你不能做到这一点。。。
使用指定所需确切格式的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);
}
}
(我无法理解为什么它会在没有AdjustToUniversal
的情况下默认调整为本地,但没关系…)
编辑:只是为了扩大我对matttymmo建议的反对意见,我的目的是证明它会丢失信息。到目前为止,我失败了,但方式很奇特。看看这个-在欧洲/伦敦时区运行,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.
看起来有一个"有或没有夏令时"标志存储在的某个地方,但如果我能弄清楚在哪里,我会大吃一惊的。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
解析它们,然后用两种不同的方式将它们转换回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.5测试版下的结果:
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
和往常一样,Jon的回答非常全面。也就是说,还没有人提到DateTimeStyles.RoundtripKind
。如果要将DateTime转换为字符串并返回到相同的DateTime(包括保留DateTime.Kind
设置),请使用DateTimeStyles.RoundtripKind
标志。
正如Jon所说,正确的做法是在将DateTime对象转换为字符串时使用"O"格式化程序。这样既保留了精度信息,又保留了时区信息。再次,正如Jon所说,在转换回时使用DateTime.ParseExact
。但如果你使用DateTimeStyles.RoundripKind,你总是会得到你输入的内容:
var now = DateTime.UtcNow;
var strNow = now.ToString("O");
var newNow = DateTime.ParseExact(strNow, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
在上面的代码中,newNow
与now
完全相同,包括它是UTC这一事实。如果运行相同的代码,除了用DateTime.Now
代替DateTime.UtcNow
之外,您将获得now
的精确副本作为newNow
,但这次是本地时间。
就我的目的而言,这是正确的,因为我想确保传递和转换的东西都转换回完全相同的东西。
使用以下TimeZoneInfo
类:
var myDate = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2012-09-30T23:00:00.0000000Z"));
您可以为解析器方法使用以下格式:yyyy-MM-ddTHH:mm:ss.ffffffK
这将在结束时正确处理时区信息(从.NET 2.0开始)。
回复:ISO 8601
之前遇到过类似的问题,几个小时后(并拔出了头发)最终使用了DateTime.SpecificKind:
DateTime.SpecifyKind(inputDate, DateTimeKind.Utc);
我相信有人在上面的评论中也回避了这一点。