【问题标题】:With the Win 10 Oct 2018 update, Windows is leap second aware. Is .NET's DateTime, too, now?随着 Win 10 Oct 2018 更新,Windows 可以感知闰秒。现在也是 .NET 的 DateTime 吗?
【发布时间】:2019-09-21 15:50:22
【问题描述】:

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 框架使用 它自己的内部逻辑来确定现在是什么时间,什么时候不是 考虑闰秒。因此,依赖于 .NET Framework,使用时不会报告第 61 秒(数字 60) 获取日期

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

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

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

[1]Are .Net's DateTime methods capable of recognising a Leap Second?

[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)

【问题讨论】:

  • 分页@JonSkeet...
  • “闰秒感知”到底是什么意思?您仍然无法用 60 秒初始化 DateTime 结构:ideone.com/mrublk, docs.microsoft.com/en-us/dotnet/api/…
  • 除了大量的注册表黑客来打开它之外,应用程序还需要调用 GetSystemTime() 或 GetLocalTime() winapi 函数来观察 60 秒的值。将系统时钟破解为 hh/mm/ss 的唯一功能。 CLR 和框架都不使用这些功能,您必须使用 pinvoke。
  • @HansPassant,看起来是这样,但显然,幕后发生了一些事情,请参阅我的编辑。
  • @Herb Jon Skeet 对日期和时间了解一两件事,将 Joda Time 移植到 Noda Time。见codeblog.jonskeet.uk/category/nodatime

标签: .net datetime time utc leap-second


【解决方案1】:

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

虽然 UTC 知道偶尔会插入闰秒(并且有争议 [1]),但在 Windows Server 2019 和 Windows 10 October 2018 更新之前的 .NET 的 DateTime 结构却没有,[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]

请注意,在 DateTime 结构中输入 23:59:60 作为时间会导致 .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

【讨论】:

    【解决方案2】:

    [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),.NET 将首先通过调用 Windows API 进行检查,如果这 是有效的闰秒,然后将其转换为秒数 59。如果是 无效的闰秒,那么我们将抛出异常。

    .NET 没有改变 为了应用程序的兼容性,DT 和 DTO 如何工作,因为我们 知道许多用户在他们的代码中做同样的假设 总是有分钟是 60 秒。和不同系统中的滴答声 不能表示不同的时间。如果您还有其他问题,请告诉我 或者您需要更多说明

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-04
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 2015-12-12
      相关资源
      最近更新 更多