Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DateTime.ToLocalTime与夏令时不正常工作_C#_.net_Datetime_Timezone - Fatal编程技术网

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,直到最后一分钟,然后转换为本地时间进行输出

编辑:或者相反,如果您不希望在添加或扣除天数时更改本地小时和分钟,请在添加
时间跨度
之前转换为本地时间然而,正如马特·约翰逊正确指出的那样,通过这种方式,您可能会得到一个无效(时钟在该时间内向前移动)或不明确(时钟向后移动,因此时间出现两次)的本地时间。有关如何确定这一点,请参见下面他的评论。

几点:

  • TimeSpan
    表示经过的持续时间。它的“天”是标准的天,正好24小时长

  • 在所讨论的那天,在当地时区,由于DST后退转换,有25个小时

  • DateTime
    对象的添加(通过
    +
    运算符或
    Add…
    函数)始终不考虑时区。换句话说,无论原始的
    .Kind
    属性是什么,输出都将具有相同的
    .Kind
    属性,但在加法/减法过程中根本不考虑种类

  • 因此,转换为当地时间后添加不包括每天25小时。这也是有问题的,因为可能会在不存在或存在两次的本地时间值上着陆

因此,当您在代码注释中说“是否考虑夏令时”时,从技术上讲,您将其颠倒过来。由于UTC没有转换,因此
localizedFirst
变量是错误地假设本地日为24小时的结果,而
addedFirst
变量是在时间线上原始时间点24小时后正确应用本地时区DST规则的结果

另外,设置
DateTimeKind.Unspecified
不会改变这种情况的效果,因为
DateTime.ToLocalTime()
方法将
DateTimeKind.Unspecified
视为
DateTimeKind.Utc
。事实上,我试图复制您的结果,但仅仅通过更改类型,无法使
dt2
的值有任何不同。如果可以,请具体阐述这一点

值得指出的是,消除这种混淆正是该库存在的原因。在野田佳彦时代,这些都由两种截然不同的操作来表示:

  • LocalDateTime+Period=LocalDateTime
  • Instant+Duration=Instant

您使用的是什么版本的.NET?2.0/3.5运行时处理日期的方式与4.x运行时不同。几年前,我遇到了很多矛盾。从那时起,这些问题可能已经得到解决,但无论哪种方式,框架版本都会有所帮助。也许本文可以帮助您提供特定的时间和时区(什么时区,dt是什么时间,夏时制何时在该区域生效)?因为这对这类问题很重要。但一般来说,日期时间的算术运算(如增加天数-您的情况)不考虑夏令时,而转换运算(如ToLocalTime-您的情况)则考虑夏令时。又是一年中的时间了。发生的情况完全正常,(dt+ts)仍然是utc,因此可以针对dst进行适当调整。但是本地时间+ts保持本地时间。因为当地时间不明确,所以无法调整。这里的另一个重要问题是:您是否恰好在亚利桑那州或夏威夷州(不调整DST的州)?是的,这是正确的,只是
localizedFirst
的结果可能无效或不明确。
是无效时间
是无效时间