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时间的字符串?

非常感谢!

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

我会亲自使用我的Noda Time项目。(诚然,作为作者,我有偏见,但它会更干净…)但如果你不能做到这一点。。。

使用指定所需确切格式的DateTime.ParseExact,并在解析代码中包括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的情况下默认调整为本地,但没关系…)

编辑:只是为了扩大我对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);

在上面的代码中,newNownow完全相同,包括它是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);

我相信有人在上面的评论中也回避了这一点。