Windows FILETIME结构是否包含闰秒?

时间:2008-09-24 23:24:46

标签: windows datetime filetime leap-second

根据Microsoft文档,FILETIME structure从1601年1月1日开始计算(可能是当天的开始),但这是否包括闰秒?

7 个答案:

答案 0 :(得分:14)

问题不应该是FILETIME包含闰秒。

应该是:

  

解释FILETIME(即FileTimeToSystemTime)的人,函数和库在计算持续时间时是否包含闰秒?

简单的答案是“no”FileTimeToSystemTime0..59的形式返回秒数。


更简单的答案是:“当然不是,怎么可能?”。

我的Windows 2000机器不知道自发布以来十年内增加了2个闰秒。它对FILETIME的任何解释都是错误的。


最后,我们可以通过直接的实验观察来确定海报问题的答案,而不是依靠逻辑:

var
    systemTime: TSystemTime;
    fileTime: TFileTime;
begin
    //Construct a system-time for the 12/31/2008 11:59:59 pm
    ZeroMemory(@systemTime, SizeOf(systemTime));
    systemtime.wYear := 2008;
    systemTime.wMonth := 12;
    systemTime.wDay := 31;
    systemTime.wHour := 23;
    systemtime.wMinute := 59;
    systemtime.wSecond := 59;

    //Convert it to a file time
    SystemTimeToFileTime(systemTime, {var}fileTime);

    //There was a leap second 12/31/2008 11:59:60 pm
    //Add one second to our filetime to reach the leap second
    filetime.dwLowDateTime := fileTime.dwLowDateTime+10000000; //10,000,000 * 100ns = 1s

    //Convert the filetime, sitting on a leap second, to a displayable system time
    FileTimeToSystemTime(fileTime, {var}systemTime);

    //And now print the system time
    ShowMessage(DateTimeToStr(SystemTimeToDateTime(systemTime)));

添加一秒到

12/31/2008 11:59:59pm

给出

1/1/2009 12:00:00am

而不是

1/1/2009 11:59:60pm

Q.E.D。

原始海报可能不喜欢它,但上帝故意操纵它,以便一年不能被一天整除。他这样做只是为了搞砸程序员。

答案 1 :(得分:9)

Here提供了有关为何选择特定日期的更多信息。

  

FILETIME结构记录时间   100纳秒间隔的形式   从1601年1月1日起。为什么会这样   选择日期?

     

格里高利历是以a为准   400年周期,1601是第一个   活跃的周期年份   Windows NT的时间   设计的。换句话说,它是   选择让数学出来   很好。

     

我实际上收到了戴夫的电子邮件   卡特勒证实了这一点。

答案 2 :(得分:8)

如果没有先决定,这个问题就没有单一答案:Windows FILETIME实际上是在计算什么?微软的文档称自1601年UTC以来它的间隔为100纳秒,但这是有问题的。

在1960年以前,没有任何形式的国际协调时间。在1964年以前的任何文献中都没有出现UTC这个名称。作为官方名称的UTC名称直到1970年才存在。但它变得更糟。皇家格林威治天文台直到1676年才建立起来,所以即使试图将FILETIME解释为格林威治标准时间也没有明确的含义,只有在那时,精确擒纵机构的摆钟开始给出1秒的精度。

如果FILETIME被解释为平均太阳秒,则自1601以来的闰秒数为零,因为UT没有闰秒。如果FILETIME被解释为有原子计时器那么自1601以来的闰秒数约为-60(这是负60闰秒)。

那是古代历史,那么自原子计时器以来的时代呢?这并不好,因为各国政府没有区分平均太阳秒和SI秒。十年来,ITU-R一直在讨论放弃闰秒,但尚未达成国际共识。部分原因可以从中看到 javascript on this page(另请参阅该页面上的delta-T链接以了解古代历史的情节)。由于各国政府尚未明确区分,因此根据某些司法管辖区的法律,任何定义自1972年以来的秒数的企图都存在无效的风险。 ITU-R的代表也意识到了这种复杂性,POSIX委员会的成员也是如此。在制定外交问题之前,在国家政府和国际标准在平均太阳能和SI秒之间作出明确的区分和选择之前,计算机标准几乎没有希望效仿。

答案 3 :(得分:2)

IERS不可预测地添加了闰秒。自1972年以来,已经定义了23秒,当时定义了UTC和闰秒。维基百科说“因为从长远来看地球的轮换速度是不可预测的,所以不可能提前六个月预测它们的需要。”

由于您必须保留插入闰秒的历史记录,并不断更新操作系统以保留插入时间的参考,并且差异非常小,所以不要指望一般性 - 用于补偿闰秒的操作系统。

此外,与UTC相比,PC中简单电子钟的常规时钟漂移远大于闰秒所需的补偿。如果您需要这种精度来补偿闰秒,则不应使用高度不准确的PC时钟。

答案 4 :(得分:1)

此问题的答案曾经是“否”,但已更改为:是,有时, ...

the Windows Networking team blog article

  

从Server 2019和Windows 10 October [2018]更新时间开始,API现在将考虑操作系统在将FILETIME转换为SystemTime时意识到的所有leap秒。

由于自添加此功能以来没有发布过leap秒,因此操作系统仍然不知道任何any秒。但是,当下一个正式的leap秒进入世界时,启用了此新功能的Windows计算机将对其进行跟踪,因此FILETIME的值将被计算机上的leap秒数所抵消。解释它们的时间。

博客文章继续描述:

  

未更改FILETIME。自历元开始以来,它仍然代表100 ns的间隔数。改变的是该数字在转换为SYSTEMTIME并返回时的解释。以下是受影响的API的列表:

     
      
  • GetSystemTime
  •   
  • GetLocalTime
  •   
  • FileTimeToSystemTime
  •   
  • FileTimeToLocalTime
  •   
  • SystemTimeToFileTime
  •   
  • SetSystemTime
  •   
  • SetLocalTime
  •   
     

在此版本之前,SYSTEMTIME的wSecond的有效值介于0到59之间。现在,SYSTEMTIME已更新为允许值60,条件是年,月和日表示a秒的有效日期。 / p>      

...

     

为了在SYSTEMTIME结构中接收60秒,必须显式选择进程。

请注意,选择加入适用于在如何将FILETIME映射到SYSTEMTIME上列出的功能内的行为。无论您是否选择加入,操作系统仍然会根据其知道的the秒来偏移FILETIME的值。

关于兼容性,文章指出:

  

依赖于第三方框架的应用程序应确保其框架在Windows上的实现也调用正确的API以计算正确的时间,否则应用程序将报告错误的时间。

并且还提供了指向an earlier post的链接,该链接描述了如何禁用整个功能,如下所示:

  

...您可以恢复到以前的操作系统行为,并通过添加以下注册表项全面禁用leap秒:

     
      
  • HKLM:\SYSTEM\CurrentControlSet\Control\LeapSecondInformation
  •   
  • 类型:“ REG_DWORD”
  •   
  • 名称:已启用
  •   
  • 值:0禁用系统范围的设置
  •   
  • 值:1启用系统范围的设置
  •   
     

下一步,重新启动系统。

答案 5 :(得分:0)

非常粗略的总结:

UTC =(原子时间)+(闰秒)~~(平均太阳时)

MS文档特别指出“UTC”,因此应包括闰秒。与MS一样,您的里程可能会有所不同。

答案 6 :(得分:0)

根据这个comment窗口完全没有意识到闰秒。如果你向今天1:39:45的FILETIME添加24 * 60 * 60秒,你将获得一个代表明天1:39:45的FILETIME,无论如何。