3

2012 年,这里有一个关于 SO 的问题,.NET 的 DateTime 是否能够识别闰秒。[1] 答案是否定的。

该文档仍然明确指出它不是。[2]

但是,Windows Server 2019 和 2018 年 10 月 10 日的 Windows 更新使Windows 本身具有闰秒意识。[3]

这就引出了一个问题:.NET 现在是否天生具有闰秒意识?更具体地说:我是否可以通过某种方式选择加入,让我的DateTime结构也能感知秒级?

编辑:

来自题为“任务:在 Windows 上编写闰秒感知应用程序”[4](我强调)的 MS Word 文档:

已知问题:已知某些框架会在闰秒发生后错误地计算时间。例如,.NET Framework 使用它自己的内部逻辑来确定现在是什么时间。它的逻辑不考虑闰秒。因此,在操作系统引入闰秒后,“System.DateTime.Now.ToString()”的输出将比本地系统时间提前一秒。 (我们正在与 .NET 框架团队合作。)

从[5]:

众所周知,某些应用程序通过假设一分钟总有 60 秒来错误地计算时间。由于闰秒可以改变这种行为,他们将不正确地记录此事件期间的时间。例如(在撰写本文时):

.NET Framework 使用自己的内部逻辑来确定现在是什么时间,并且不考虑闰秒。因此,依赖 .NET Framework 的 PowerShell 在使用 Get-Date 时不会报告第 61 秒(数字 60)

事件查看器:事件的日期将被错误记录。但是,事件元数据会正确记录系统时间(显示第 60 秒)。

注意:这些团队正在努力更新他们的软件,以便在处理闰秒时使用更合适的数学

因此,.NET 似乎会在未来的某个时间意识到闰秒。因此,我不会将此作为解决方案发布。

[1] .Net 的 DateTime 方法是否能够识别闰秒?

[2] https://docs.microsoft.com/en-us/dotnet/api/system.datetime.ticks?redirectedfrom=MSDN&view=netframework-4.8#System_DateTime_Ticks

[3] https://support.microsoft.com/en-us/help/2722715/support-for-the-leap-second

[4] https://aka.ms/Dev-LeapSecond (MS Word)

[5] https://aka.ms/ITPro-LeapSecond (MS Word)

4

2 回答 2

3

[H] 以下是 .NET(版本 4.7.2)如何在支持闰秒的 Windows 版本(即 Windows 10 RS5 版本)上工作的一些说明:

DateTime (DT) 和 DateTimeOffset (DTO) 在如何存储时间单位以及如何对这些单位进行操作方面没有改变。这些类型只存储刻度,刻度为 100 纳秒。在刻度和日期/时间部分(例如年月、日、小时、分钟、秒、毫秒)之间进行转换时,它总是假定分钟为 60 秒且不能为 61 秒。即在滴答声或转换中不计算闰秒。

当在DT 和DTO 上调用Now 属性时,我们最终会调用Windows API(例如GetSystemTimeAsFileTime)。GetSystemTimeAsFileTime 在那里计算闰秒。因此,.NET 在启用闰秒的系统上运行时会做额外的步骤,通过调用更多可以报告系统时间的 Windows API 来获取准确时间,以确保 .NET 报告的时间与系统同步。.NET 仍然调用 GetSystemTimeAsFileTime 以获得更精确的时间(精度为 100 纳秒)。

如果 Windows 向我们报告第二个数字 60(即闰秒),.NET 将假定这是该分钟的最后一秒并将其用作第二个 59,以使其与 DT 和 DTO 无缝工作,因为这些类型不知道闰秒。

如果有人尝试使用闰秒 (60) 创建 DT 或 DTO,.NET 将首先通过调用 Windows API 检查这是否是有效的闰秒,然后将其转换为秒数 59。如果它不是有效的闰秒,则我们会抛出异常。

.NET 并没有为了应用程序的兼容性而改变 DT 和 DTO 的工作方式,因为我们知道许多用户在他们的代码中做同样的假设,即滴答始终是 60 秒。并且不同系统中的滴答不能意味着不同的时间。如果您还有其他问题或需要更多说明,请告诉我

来源:https ://github.com/dotnet/dotnet-api-docs/issues/966#issuecomment-434440807

于 2019-05-03T23:50:48.703 回答
1

通过提供更多可能感兴趣的细节来扩展已接受的答案。

虽然 UTC 意识到闰秒的偶尔插入(并且存在争议 [1]),但 .NETDateTime在 Windows Server 2019 和 Windows 2018 年 10 月 10 日更新之前的结构不是,[2] 因为 Windows 本身两者都不是。[3] [4]

但即使 Window 的内核现在可以感知闰秒,应用程序仍然不能感知,除非采取特定行动。 [5] .NET 框架本身还不支持闰秒。[6]

但是,Windows 系统通过 NTP(使用 UTC)更新它们的时间,这可以感知闰秒。 [7] 这可能会导致 Windows 系统的时间不连续,因为作为 NTP 客户端工作的 Windows 时间服务可能希望在闰秒之后的某个时间下一次同步时立即同步系统时间,这可能导致时钟向后跳 1 秒。 [8]

当然,负时间值的出现可能(在 Linux 系统上确实 [9​​][10])会导致不良或不可预知的行为,这就是 Windows 不允许这种情况发生的原因。

调用DateTime.Now方法时,将调用闰秒感知 Windows API 函数GetSystemTimeAsFileTime。当获得 23:59:60 UTC 闰秒时,它被视为 23:59:59 UTC 的第二次出现,而不重新计算 100 ns 滴答声,但将那一秒的所有 1000 万个滴答声保持在可能的最大滴答计数取而代之的是,计时实际上会暂停一秒钟。 [11]

请注意,在结构中输入 23:59:60 作为时间DateTime会导致 .Net 根据迄今为止发生的闰秒执行检查。如果它确实是一个,它将被接受(但转换为 23:59:59)。 [11]


[1] 国际地球自转和参考系统服务(IERS);协调世界时 (UTC) 以保留“闰秒” – https://www.iers.org/SharedDocs/Publikationen/EN/IERS/Publications/messages/IERS_Message_No_282.html

[2] 微软;DateTime.Ticks 属性 – https://docs.microsoft.com/en-us/dotnet/api/system.datetime.ticks?redirectedfrom=MSDN&view=netframework-4.8#System_DateTime_Ticks

[3] 微软;Windows 时间服务如何处理闰秒 – https://support.microsoft.com/en-us/help/909614/how-the-windows-time-service-treats-a-leap-second

[4] 微软;支持闰秒 – https://support.microsoft.com/en-us/help/2722715/support-for-the-leap-second

[5] 微软;开发人员的闰秒验证 – https://aka.ms/Dev-LeapSecond

[6] 微软;IT 专业人员的闰秒验证 – https://aka.ms/ITPro-LeapSecond

[7] D. Mills(特拉华大学);闰秒处理 - https://www.eecis.udel.edu/~mills/ntp/html/leap.html

[8] 微软;Windows 时间服务如何处理闰秒 – https://support.microsoft.com/en-us/help/909614/how-the-windows-time-service-treats-a-leap-second

[9] 有线;“闰秒”错误在网络上造成严重破坏 – https://www.wired.com/2012/07/leap-second-bug-wreaks-havoc-with-java-linux/

[10] /root.in; Linux 内核中的闰秒错误 – https://www.slashroot.in/leap-second-bug-linux-kernel

[11] GitHub;闰秒声明令人困惑 – https://github.com/dotnet/dotnet-api-docs/issues/966#issuecomment-434440807

于 2019-05-05T15:33:23.867 回答