为什么日期时间上的独立操作顺序(添加和到本地时间/到世界时间)会改变结果?



这两行产生的结果相同(结果在我的时区),这是预期的:

new DateTime(1970, 1, 1).ToLocalTime().AddHours(10000) // [21.02.1971 17:00:00]
new DateTime(1970, 1, 1).AddHours(10000).ToLocalTime() // [21.02.1971 17:00:00]

现在,这两行会产生两种不同的结果:

new DateTime(1970, 1, 1).ToLocalTime().AddHours(100000) // [29.05.1981 17:00:00]
new DateTime(1970, 1, 1).AddHours(100000).ToLocalTime() // [29.05.1981 18:00:00]

这似乎真的很奇怪,我不太明白为什么会发生这种情况。我知道 Jon Skeet 会争辩说我们根本不应该使用DateTime,因为它不够好,而是使用nodatime,但出于好奇,知道为什么会发生这种情况很有趣。

从逻辑上讲,时间点不会根据操作顺序而改变,并且它仍然是相同的时间,尽管显然它不在 C# 中。

附言ToUniveralTime的行为方式相同,并在第二个示例中产生 2 个不同的结果(偏差一小时)。

我假设你在英国(我们在那里度过了UTC的冬天,但在夏天切换到UTC + 1)。因此,在 1970 年 1 月 1 日午夜,我们处于 UTC 状态。

  • 除了Kind更改为本地之外,new DateTime(1970, 1, 1).ToLocalTime()什么都不做,因为 DateTime 假定我们以 UTC 指定了一个时间点。然后我们加上 10,000 小时,这使我们到达冬季时间的某个点。
  • new DateTime(1970, 1, 1).AddHours(10,000)也把我们带到了冬季 UTC 的某个点,所以.ToLocalTime()再次什么都不做,除了将 Kind 更改为 Local。

但是,当我们增加 100,000 小时时,情况会有所不同,因为这会在夏令时开始后将我们带到一个点。

  • new DateTime(1970, 1, 1).ToLocalTime().AddHours(100000)像以前一样Kind更改为本地,然后添加 100,000 小时的刻度。我们从UTC转移到UTC+1并没有被欣赏。
  • 然而,new DateTime(1970, 1, 1).AddHours(100000)将我们带到了本地时间和 UTC 不同的时间点,因为我们是在 1981 年 3 月 29 日之后,夏令时已经开始。 因此,.ToLocalTime()发现存在 1 小时的差异并将其相加,从而得出提前 1 小时的时间。

值得记住的是DateTime的行为方式。它代表一个瞬间 - 自一个纪元以来的刻度数。它还有一个Kind属性,该属性说明该时间是基于本地时间、UTC 还是"未指定"(即您尚未告知它)。

例如,new DateTime(1980, 4, 1, 0, 0, 0, DateTimeKind.Local)(我在 DST 之后选择了日期),new DateTime(1980, 4, 1, 0, 0, 0, DateTimeKind.Utc)Ticks属性具有相同的值,并且它们打印相同的字符串。但是,调用.ToLocalTime()会做不同的事情:在第一种情况下,它什么都不做(因为DateTime已经是本地时间),但在第二种情况下,它会为DateTime添加一个小时的刻度

。因此,请记住,请始终跟踪Kind是什么,并注意它在UTC/本地时间之间转换时的影响。DateTime本身并不是特别聪明,但时区转换方法确实有很多围绕Kind的特殊情况逻辑,这可能会抛弃你。

我认为您可能应该使用DateTimeOffset而不是DateTime- 它显示了您当前所处的时区,并消除了"未指定"和"我的 PC 所在的任何时区"的毛茸茸的概念。尝试对DateTimeOffsets重复此实验。

最新更新