这两行产生的结果相同(结果在我的时区),这是预期的:
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
重复此实验。