这两行产生相同的结果(结果在我的时区中),这是预期的:
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#中。
P.S。 ToUniveralTime
的行为相同,在第二个示例中产生2个不同的结果(相差一小时)。
答案 0 :(得分:3)
我假设您在英国(冬天我们在UTC度过,但在夏天改用UTC + 1)。因此,1970年1月1日午夜,我们使用UTC。
new DateTime(1970, 1, 1).ToLocalTime()
除了将Kind
更改为Local以外,什么也不做,因为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
更改为Local,然后增加了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)
(我选择的是夏令时之后的日期),而new DateTime(1980, 4, 1, 0, 0, 0, DateTimeKind.Utc)
的{{1}}属性具有 same 值,并打印出相同的字符串。但是,调用Ticks
会执行不同的操作:在第一种情况下,它什么都不做(因为.ToLocalTime()
已经在本地时间了),但是在第二种情况下,它会给{{1 }}。
因此请记住,始终跟踪DateTime
是什么,并注意它在UTC /本地时间之间转换时的影响。 DateTime
本身并不是特别聪明,但是时区转换方法 do 在Kind
周围有很多特殊情况的逻辑,它们可能会让您失望。
我认为您可能应该使用DateTime
而不是Kind
-这可以向您显示您当前所在的时区,并消除了“未指定”和“我的PC处于任何时区”。尝试使用DateTimeOffset
重复此实验。