Datetime 隐式转换为 Datetimeoffset 会导致不正确的偏移量?

Posted

技术标签:

【中文标题】Datetime 隐式转换为 Datetimeoffset 会导致不正确的偏移量?【英文标题】:Datetime implicit conversion to Datetimeoffset results in incorrect offset? 【发布时间】:2016-03-11 20:21:08 【问题描述】:

在尝试确定给定的 datetimeoffset 是否发生在时区调整(夏令时)的开始或结束时,我注意到一些奇怪的事情。 而且我不确定我是不是走错了路。

以如下代码为例:

class Program

    static void Main(string[] args)
    
        // Note: this is done on a swedish computer.
        int year = 2015;
        DateTimeOffset dateTimeJustBeforeOffsetChanges = new DateTime(year, 10, 25, 1, 59, 59);
        DateTimeOffset dateTimeRightWhenOffsetChanges = new DateTime(year, 10, 25, 2, 0, 0); // 2015-10-25 02:00:00. This is how we set our offset. We let the implicit conversion do all the work :)

        var daylightSavings = TimeZone.CurrentTimeZone.GetDaylightChanges(year);

        Console.WriteLine(dateTimeJustBeforeOffsetChanges); // Prints out 2015-10-25 01:59:59 +02:00
        Console.WriteLine(dateTimeRightWhenOffsetChanges); // Prints out 2015-10-25 02:00:00 +01:00 This is the exact time when the datetimeoffset starts using offset +02 instead of +01
        Console.WriteLine(daylightSavings.End.ToString()); // Prints out 2015-10-25 03:00:00
        Console.ReadLine();
    

从上面的代码可以看出,当使用从 datetime 到 datetimeoffset 的隐式转换时,偏移量在 10 月 25 日凌晨 2 点从 +1 小时变为 +2 小时。但是,当使用 GetDaylightChanges 方法分析当前夏令时时,系统会告知更改应该发生在 10 月 25 日的 3 点。

在我的脑海中,偏移量应该在 3 点钟变为 +2,而不是 2 点钟,还是我错了?

PS:此代码在具有瑞典时区设置的瑞典机器上运行。

【问题讨论】:

您通常应该避免使用TimeZone - TimeZoneInfo 通常是一个更合适的类,尽管我个人仍然觉得它有些可恶。顺便说一句,在我的 Noda Time 项目中,所有这些都更简单:) 是的,当我读到使用 TimeZone 类更简单的方法时,我实际上开始使用 timezoneinfo 编写这个半大型方法。作为旁注:在夏令时开始时也会出现同样的问题。 'GetDaylightChanges' 方法返回的日期时间几乎就像是 UTC 日期时间...... 也许我理解错了,但是你在这个问题中反复说“偏移量从+1小时变为+2小时”。你不是说从 +2 到 +1 小时吗? 【参考方案1】:

首先,GetDaylightChanges 是准确的 - clocks did go back in Sweden at 3am local time。

其次,这并不意味着您在 BCL 的任何地方都显示了错误。问题只是 02:00:00 发生了两次 - 一次在时钟返回之前,一次在之后。换句话说,它发生在 2015-10-25 02:00:00 +02:00 和 2015-10-25 02:00:00 +01:00。您如何期望隐式转换来判断您的意思是哪一个?两者都是有效的结果,并且恰好选择了后一个结果,尽管不幸的是,该行为未指定,至少在隐式转换文档和 DateTimeOffset 构造函数文档中都是如此。

这就是为什么在我的 Noda Time 库中,当您从 LocalDateTime 映射到 ZonedDateTime(通过应用时区)时,如果值不明确,您必须说出您想要发生的事情或跳过 - 因此在这种情况下,您可以选择将其解析为 2015-10-25 02:00:00 的较晚或较早出现。

基本上这是你应该考虑的事情,并决定你希望你的应用程序如何表现......然后你应该指定你想要的行为,使用你正在使用的任何 API。这在某些 API 中比在其他 API 中更容易:)

【讨论】:

接受您的回答,因为您以帮助我解决问题的方式解释了问题:)。我最终使用夏令时增量来确定提供的日期是在时区调整的开始还是结束。

以上是关于Datetime 隐式转换为 Datetimeoffset 会导致不正确的偏移量?的主要内容,如果未能解决你的问题,请参考以下文章

无法将类型“System.DateTime”隐式转换为“string”

无法将类型“System.DateTime”隐式转换为“string”是啥意思?怎么改正?

asp.net 无法将类型“System.DateTime”隐式转换为“string”

DataContractJsonSerializer DateTime 隐式时区转换

获取“'<null>' 和 'System.DateTime' 之间没有隐式转换”错误消息 [关闭]

MaxCompute问答整理之12月