2016-11-10 88 views
1

我正在研究DateTimeBCL中的相关类别的“机制”。 我对以下奇怪的行为感兴趣。请看下面的代码片段:日期时间和偏移微妙

var dt1 = new DateTime(2014, 10, 24, 15, 30, 00, DateTimeKind.Unspecified); 
DateTimeOffset dto2 = new DateTimeOffset(dt1, TimeSpan.FromHours(6)); 
string input = dto2.ToString("o"); 
DateTime dt6 = DateTime.Parse(input, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); 
Console.WriteLine("DT6:" + dt6.ToString("o")); 

我知道我应该解析字符串到DateTimeOffset,但我只是想知道为什么图书馆可以让我做什么,我在这里做,最有趣的事情是为什么输出将是:"DT6:2014-10-24T13:30:00.00000000+04:00" 它在解析过程中做了什么,它将偏移量设置为本地计算机时区中给定时间段的实际偏移量,并通过初始偏移量和生成的偏移量之间的增量调整小时数。 无论我提供什么作为DateTimeStyles选项,它都这样做。结果值的类型设置为Local,无论是否提供Roundtrip值也不论。 所以问题是为什么默认设置为Local,第二个问题是DateTime存储的偏移量,如果它存储它,为什么我们需要DateTimeOffset类?

+0

日期时间只能存储UTC或本地时间。因此,如果字符串指定时区偏移量,则其Parse()方法必须执行* something *。你看到一个合理的选择,你没有指定DateTimeStyles.AdjustToUniversal。如果你需要知道偏移量,那么你当然必须使用DateTimeOffset.Parse()。至少有一个理由你为什么需要它。 –

+0

@HansPassant我很惊讶,DateTime实际上可以存储偏移量。它是否作为TimeSpan存储在内部,难道你不知道吗?然后有趣的问题(虽然我觉得这是一个修辞问题)是为什么DateTimeOffset被引入的情况下DateTime本身以某种方式试图处理偏移? – EngineerSpock

+4

它不存储偏移量。它使用2位来跟踪DateTimeKind。 Parse()方法足够聪明以处理字符串中的偏移量与DateTime可以存储的内容无关。 –

回答

1

有几件事情:

  • DateTimeDateTimeOffset均为结构,而不是类。他们是value types

  • 您的问题归结为了解DateTime.Parse方法的行为 - 而不是DateTime结构。我建议阅读the docs该方法。那里有很多很好的信息来描述你所看到的行为的微妙之处。

  • 的文档有此说关于返回类型in the "Return value" section(重点煤矿):

    一般来说,Parse方法返回一个DateTime对象,其Kind属性为DateTimeKind.Unspecified然而, Parse方法也可以执行时区转换并设置类属性的值不同,这取决于sstyles参数的值:

    chart

    你在s参数中传递值"2014-10-24T15:30:00.0000000+06:00",该参数包含时区偏移量,因此您受到图表第一行的影响,并且结果会转换为您计算机的本地时区,无论这可能是什么。

  • DateTimeStyles.RoundTripKind标志在这里不会有任何影响。如果您的输入以Z而非偏移量结尾,则只会应用上图中的第三行。在这种情况下,RoundTripKind标志确保DateTimeKind.Utc。没有它,你仍然可以得到DateTimeKind.Local

  • 不存储偏移量。在DateTime中唯一存储是将TicksKind属性合并为一个64-bit private field的值。

    作为一个有趣的边注,认识到因为这个字段中的两个比特保留类,有可能的状态,即使只有三个DateTimeKind曝光值。事实上,有一个隐藏的第四样的,这是根据“日期时间的深黑暗的秘密”,在this articlein the references sources描述。 (基本上,它是DateTimeKind.Local上的变体。)

  • 如果您想要一个更好的日期/时间API,请考虑使用Noda Time

+0

马特,非常感谢。马特,我看过你的Pluralsight课程,这非常有趣。有可能我会在莫斯科的DotNext会议上发言,希望我会谈谈.NET中的日期和时间。这就是为什么我试图收集有关这个话题的最有趣的东西。 – EngineerSpock

+0

至于主题。如果DateTime只包含上面提到的两部分数据,那么当我使用“o”格式调用ToString时,偏移量来自哪里? – EngineerSpock

+0

从您当地的时区。全球为您的电脑设置的Windows。 –

相关问题