【发布时间】:2018-04-20 00:23:09
【问题描述】:
我有一个带有Kind = DateTimeKind.Utc 和时间跨度的DateTime 实例。
var dt = DateTime.UtcNow;
var ts = TimeSpan.FromDays(1);
由于夏令时,当我本地化 dt 然后添加 ts 时,我得到的结果与添加 ts 然后本地化时不同。
var localizedFirst = dt.ToLocalTime() + ts; //Does account for daylight savings
var addedFirst = (dt + ts).ToLocalTime(); //Does not account for daylight savings
这看起来很奇怪。不应该从本地化添加偏移量和从时间跨度添加偏移量是可交换和关联的吗?
我发现了一个类似的问题:Why doesn't DateTime.ToLocalTime() take into account daylight savings? 这个问题更多地涉及将DateTime 转换为String 和从String 转换。我只使用DateTime 和TimeSpan 算术。
该问题的最佳答案建议使用DateTimeKind.Unspecified,以便运行时假定未指定的日期是UTC,然后在本地化时正确转换它。我很惊讶这真的有效。如果我像这样创建一个新的DateTime:
var dt2 = new DateTime(dt.Ticks, DateTimeKind.Unspecified);
然后两个操作顺序都返回正确的结果,夏令时。
(dt2 + ts).ToLocalTime()
dt2.ToLocalTime() + ts
这一切在我看来都是荒谬的。为什么我需要将Utc 日期转换为Unspecified 只是为了将其正确转换为Local?这似乎应该被视为一个错误。
其他细节:
- 框架:.NET 4.6.1
- 我的本地时区:东部标准时间(美国)
-
dt使用的实际值:11/5/2017 2:36:13pm UTC -
ts使用的实际值:TimeSpan.FromDays(699) -
dt的本地等效项:11/5/2017 9:36:13am -
(dt + ts).ToLocalTime()的值:10/5/2019 10:36:13am -
dt.ToLocalTime() + ts的值:10/5/2019 9:36:13am
【问题讨论】:
-
您使用的是什么版本的 .NET? 2.0/3.5 运行时处理日期的方式与 4.x 运行时不同。几年前,我遇到了很多差异。从那时起它们可能已经得到解决,但无论哪种方式,框架版本都会有所帮助。
-
您能否提供具体的时间和时区(什么时区,dt 时间,夏令时在该地区生效的时间)?因为它对这类问题很重要。但总的来说 - 日期时间的算术运算(如添加天数 - 您的情况)不会考虑夏令时,而转换操作(如 ToLocalTime - 也是您的情况)会。
-
又到了一年的时间。发生的事情是完全正常的,(dt + ts) 仍然是 utc,因此可以针对 dst 进行适当调整。但当地时间 + ts 保持当地时间。并且无法调整,因为当地时间不明确。
-
这里还有一个重要的问题:您是否恰好在亚利桑那州或夏威夷(不针对 DST 进行调整的州)?