我有一个带有DateTime
和时间跨度的Kind = DateTimeKind.Utc
实例。
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
相互转换。我仅使用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
最佳答案
几点:TimeSpan
表示经过的时间长度。它的“天”是标准时间,恰好是24小时。
在该日的当地时区,由于DST后备转换,因此有25个小时。
总是在不考虑时区的情况下(通过DateTime
运算符或+
函数)添加Add...
对象。换句话说,无论原始的.Kind
属性是什么,输出都将具有相同的.Kind
属性,但是在加/减过程中根本不考虑该类型。
因此,在转换为本地时间后进行添加不会占25小时的一天。这也是有问题的,因为有可能落在一个不存在或存在两次的本地时间值上。
因此,当您在代码注释中说“是否(或不)考虑夏时制”时,从技术上讲,您将其撤消了。由于UTC没有过渡,因此localizedFirst
变量是错误地假定本地日期为24小时的结果,而addedFirst
变量是正确地从本地时区应用DST规则的结果,即在时间轴上的原始点之后经过了24小时。
同样,设置DateTimeKind.Unspecified
不会改变这种情况的效果,因为DateTime.ToLocalTime()
方法会将DateTimeKind.Unspecified
视为DateTimeKind.Utc
。 See the table in the remarks of the documentation here.的确,我试图复制您的结果,并且仅仅通过改变种类就无法使dt2
的值有所不同。如果可以,请具体说明这一点。
值得指出的是,消除这种混淆正是Noda Time库存在的原因。在Noda Time中,这些操作由两种截然不同的操作表示:LocalDateTime + Period = LocalDateTime
Instant + Duration = Instant
关于c# - DateTime.ToLocalTime与夏令时不能正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47160663/