C# DateTime.ToLocalTime与夏令时不正常工作
我有一个C# DateTime.ToLocalTime与夏令时不正常工作,c#,.net,datetime,timezone,C#,.net,Datetime,Timezone,我有一个DateTime实例,带有Kind=DateTimeKind.Utc和一个timespan var dt = DateTime.UtcNow; var ts = TimeSpan.FromDays(1); 由于夏令时的原因,当我本地化dt然后添加ts时,我得到的结果与添加ts然后本地化时不同 var localizedFirst = dt.ToLocalTime() + ts; //Does account for daylight savings var addedFirst = (
DateTime
实例,带有Kind=DateTimeKind.Utc
和一个timespan
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
这似乎很奇怪。从本地化添加偏移量和从时间跨度添加偏移量不应该是可交换和关联的吗
我发现了一个类似的问题:这个问题更多的是处理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
?这似乎应该被视为一个bug
其他详情:
- 框架:.NET 4.6.1
- 我的本地时区:东部标准时间(美国)
使用的实际值:dt
11/5/2017 2:36:13pm UTC
使用的实际值:ts
TimeSpan.FromDays(699)
:dt
2017年11月5日上午9:36:13am
:(dt+ts)的值。ToLocalTime()
10/5/2019 10:36:13am
:dt.ToLocalTime()+ts的值
2019年10月5日9:36:13am
var localizedFirst = dt.ToLocalTime() + ts;
虽然本声明询问24小时(经过的时间)过后的当地时间:
var addedFirst = (dt + ts).ToLocalTime();
这是一个很好的理由,可以将所有内容保持在UTC,直到最后一分钟,然后转换为本地时间进行输出
编辑:或者相反,如果您不希望在添加或扣除天数时更改本地小时和分钟,请在添加时间跨度
之前转换为本地时间然而,正如马特·约翰逊正确指出的那样,通过这种方式,您可能会得到一个无效(时钟在该时间内向前移动)或不明确(时钟向后移动,因此时间出现两次)的本地时间。有关如何确定这一点,请参见下面他的评论。几点:
表示经过的持续时间。它的“天”是标准的天,正好24小时长TimeSpan
- 在所讨论的那天,在当地时区,由于DST后退转换,有25个小时
- 对
对象的添加(通过DateTime
运算符或+
函数)始终不考虑时区。换句话说,无论原始的Add…
属性是什么,输出都将具有相同的.Kind
属性,但在加法/减法过程中根本不考虑种类.Kind
- 因此,转换为当地时间后添加不包括每天25小时。这也是有问题的,因为可能会在不存在或存在两次的本地时间值上着陆
localizedFirst
变量是错误地假设本地日为24小时的结果,而addedFirst
变量是在时间线上原始时间点24小时后正确应用本地时区DST规则的结果
另外,设置DateTimeKind.Unspecified
不会改变这种情况的效果,因为DateTime.ToLocalTime()
方法将DateTimeKind.Unspecified
视为DateTimeKind.Utc
。事实上,我试图复制您的结果,但仅仅通过更改类型,无法使dt2
的值有任何不同。如果可以,请具体阐述这一点
值得指出的是,消除这种混淆正是该库存在的原因。在野田佳彦时代,这些都由两种截然不同的操作来表示:
LocalDateTime+Period=LocalDateTime
Instant+Duration=Instant
localizedFirst
的结果可能无效或不明确。是无效时间
和是无效时间