ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – IsDayLightSavingTime方法为同一时区和同一时间返回不同的值

2019-07-01 12:52:17  阅读:265  来源: 互联网

标签:c net net-4-5 dst


下面的代码检查DST中的特定时间或不返回与正常日期时间相同的时间的不同值以及从filetime获取的值:

var tzInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var reminderstarttime = new DateTime(2018, 3, 10, 22, 0, 0);
var referencetime = reminderstarttime.AddHours(10);  // ReferencedTime is in DST;

var isRemDstWithNormal = tzInfo.IsDaylightSavingTime(reminderstarttime);
var isRefDstWithNormal = tzInfo.IsDaylightSavingTime(referencetime);

var reminderStartTimeToUtc = (ulong)reminderstarttime.ToFileTimeUtc();
var referenceTimeToUtc = (ulong)referencetime.ToFileTimeUtc();

var reminderStartTimeFromUtc = DateTime.FromFileTimeUtc((long)reminderStartTimeToUtc);
var referencetimeFromUtc = DateTime.FromFileTimeUtc((long)referenceTimeToUtc);

var isRemDSTFromFileTime = tzInfo.IsDaylightSavingTime(reminderStartTimeFromUtc);
var isRefTimeDSTFromFileTime = tzInfo.IsDaylightSavingTime(referencetimeFromUtc);

Console.WriteLine("isRemDstWithNormal: " + isRemDstWithNormal + 
                 " isRefDstWithNormal: " + isRefDstWithNormal + 
                 " isRemDSTFromFileTime " + isRemDSTFromFileTime + 
                 " isRefTimeDSTFromFileTime: " + isRefTimeDSTFromFileTime);

解决方法:

佐哈尔大概是正确的.关键点是DateTime.ToFileTimeUtc与许多处理DateTime的方法一样,取决于与值关联的Kind.当传递DateTimeKind.Unspecified时,此特定方法假定输入已经是UTC.但是,在您的代码中,您创建的这些值就像它们所给定的时区一样.

让我们归咎于罪魁祸首:

var reminderStartTimeToUtc = (ulong)reminderstarttime.ToFileTimeUtc();
var referenceTimeToUtc = (ulong)referencetime.ToFileTimeUtc();

由于reminderstarttime和referencetime都具有Kind == DateTimeKind.Unspecified,因此它们的结果文件时间值不正确.特别:

reminderStartTimeToUtc:  131651928000000000
             we wanted:  131652216000000000
            difference:       -288000000000  = -8 hours

    referenceTimeToUtc:  131652288000000000
             we wanted:  131652540000000000
            difference:       -252000000000  = -7 hours

如您所见,它们的值与每个相应日期的UTC差异有所不同.

使用DateTime.FromFileTimeUtc在代码中将它们转换回来会返回具有DateTimeKind.Utc的值,这会抛出后续的DST检查:

reminderStartTimeFromUtc:  2018-03-10 22:00:00 UTC
  which is equivalent to:  2018-03-10 14:00:00 PST (UTC-8)
               we wanted:  2018-03-10 22:00:00 PST (UTC-8)

    referencetimeFromUtc:  2018-03-11 08:00:00 UTC
  which is equivalent to:  2018-03-11 00:00:00 PST (UTC-8)
               we wanted:  2018-03-11 08:00:00 PDT (UTC-8)

请注意,从PST到PDT的切换发生在太平洋标准时间02:00,因此两个值仍处于标准时间.

那么我们如何在没有黑客的情况下得到正确的结果呢?在转换为Windows文件时间之前,只需确保我们的输入值是DateTimeKind.Utc. (DateTimeKind.Local也可以,但是这里不需要涉及本地时区)

// First convert the DateTime values from their unspecified zone-specific times to UTC
var reminderStartTimeUtc = TimeZoneInfo.ConvertTimeToUtc(reminderstarttime, tzInfo);
var referenceTimeUtc = TimeZoneInfo.ConvertTimeToUtc(referencetime, tzInfo);

// Then convert THOSE values to file-times.
var reminderStartTimeToUtc = (ulong)reminderStartTimeUtc.ToFileTimeUtc();
var referenceTimeToUtc = (ulong)referenceTimeUtc.ToFileTimeUtc();

其余代码将按原样正确跟随,您将获得预期的结果.

请注意,这些方法的措辞有些令人困惑. DateTime.ToFileTimeUtc表示您正在转换为文件时间,并且具有.Kind == DateTimeKind.Unspecified的输入DateTime将被视为DateTimeKind.Utc.另一种方法DateTime.ToFileTime将Unspecified种类视为Local.但他们都同样对待Utc和Local类型,它们都产生一个Windows文件时间,这本身就是基于UTC的.

作为上述方法的替代方法,您可以使用DateTimeOffset.ToFileTime.在转换为文件时间期间,将正确考虑偏移量.

// construct a DateTimeOffset for each value
var reminderStartTimeDto = new DateTimeOffset(reminderstarttime, tzInfo.GetUtcOffset(reminderstarttime));
var referencetimeDto = new DateTimeOffset(referencetime, tzInfo.GetUtcOffset(referencetime));

// then just convert them to file times
var reminderStartTimeAsFileTime = reminderStartTimeDto.ToFileTime();
var referenceTimeAsFileTime = referencetimeDto.ToFileTime();

注意这里没有ToFileTimeUtc,因为DateTimeOffset上没有Kind,所以只有一种方法可以转换它.

最后一件事.请注意,DateTime.AddHours(10)不符合DST差距.因此,当你在谈论上午8点的PDT时,由于春季前进的差距,实际上只有9个小时.实际经过的10小时是太平洋夏令时上午9点.如果在添加10小时之前保留DateTimeOffset类型的值,则可以轻松纠正此问题.

标签:c,net,net-4-5,dst
来源: https://codeday.me/bug/20190701/1347174.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有