根据 Microsoft 文档,该FILETIME
结构从 1601 年 1 月 1 日(大概是那天开始)开始计算,但这是否包括闰秒?
7 回答
问题不应该是是否FILETIME
包含闰秒。
它应该是:
FILETIME
解释 a (ie )的人员、函数和库FileTimeToSystemTime
在计算持续时间时是否包括闰秒?
简单的答案是“不”。FileTimeToSystemTime
返回秒为0..59
.
更简单的答案是:“当然不是,怎么可能呢? ”。
我的 Windows 2000 机器不知道自发布以来的十年中增加了 2 个闰秒。它对 a 的任何解释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
量子点
原始海报可能不喜欢它,但上帝故意操纵它,使一年不能被一天整除。他这样做只是为了搞砸程序员。
以下是有关选择该特定日期的原因的更多信息。
FILETIME 结构以 1601 年 1 月 1 日以来 100 纳秒间隔的形式记录时间。为什么选择那个日期?
公历以 400 年为周期运行,1601 年是在设计 Windows NT 时处于活动状态的第一年。换句话说,选择它是为了使数学很好地得出结论。
我实际上收到了来自 Dave Cutler 的电子邮件,证实了这一点。
如果不先决定,就不可能有一个单一的答案:Windows FILETIME 实际计数是多少?微软文档说它从 1601 UTC 开始计算 100 纳秒的间隔,但这是有问题的。
在 1960 年之前不存在任何形式的国际协调时间。UTC 名称本身在 1964 年之前的任何文献中都没有出现。作为官方名称的 UTC 名称直到 1970 年才存在。但它变得更糟。皇家格林威治天文台直到 1676 年才成立,因此即使试图将 FILETIME 解释为 GMT 也没有明确的含义,直到那时,带有精确擒纵机构的摆钟才开始提供 1 秒的精度。
如果 FILETIME 被解释为平均太阳秒,那么自 1601 年以来的闰秒数为零,因为 UT 没有闰秒。如果 FILETIME 被解释为好像有原子计时器,那么自 1601 年以来的闰秒数约为 -60(即负 60 闰秒)。
那是古老的历史,自原子钟以来的时代呢?这也好不到哪里去,因为各国政府没有区分平均太阳秒和 SI 秒。十年来,ITU-R一直在讨论放弃闰秒,但尚未达成国际共识。部分原因可以 在此页面上的 javascript中看到(有关古代历史的情节,另请参见该页面上的 delta-T 链接)。由于各国政府尚未做出明确区分,因此自 1972 年以来定义秒数的任何尝试都存在根据某些司法管辖区的法律无效的风险。ITU-R 的代表和 POSIX 委员会的成员都意识到了这种复杂性。在外交问题解决之前,在各国政府和国际标准对平均太阳能和 SI 秒做出明确区分和选择之前,计算机标准能够效仿的希望渺茫。
这个问题的答案曾经是否定的,但现在变成了:是的,有点,有时......
从 Server 2019 开始,Windows 10 October [2018] 更新时间 API 现在将考虑操作系统在将 FILETIME 转换为 SystemTime 时知道的所有闰秒。
由于自添加此功能以来没有发出闰秒,因此操作系统仍然不知道任何闰秒。但是,当下一个官方闰秒进入世界时,启用了此新功能的 Windows 计算机将对其进行跟踪,因此FILETIME
值将被解释时计算机上的闰秒数所抵消.
博客文章继续描述:
FILETIME 没有改变。它仍然表示自纪元开始以来的 100 ns 间隔数。改变的是该数字在转换为 SYSTEMTIME 并返回时的解释。以下是受影响的 API 列表:
- 获取系统时间
- 获取本地时间
- 文件时间到系统时间
- 文件时间到本地时间
- 系统时间到文件时间
- 设置系统时间
- 设置本地时间
在此版本之前,SYSTEMTIME 的 wSecond 有效值介于 0 和 59 之间。SYSTEMTIME 现在已更新为允许值 60,前提是年、月和日表示闰秒有效的日期。
...
为了接收 SYSTEMTIME 结构中的 60 秒,进程必须明确选择加入。
请注意,选择加入适用于列出关于 a 如何FILETIME
映射到 a的函数中的行为SYSTEMTIME
。无论您是否选择加入,操作系统仍将FILETIME
根据它所知道的闰秒偏移值。
关于兼容性,文章指出:
依赖 3rd 方框架的应用程序应确保其框架在 Windows 上的实现也调用正确的 API 以计算正确的时间,否则应用程序将报告错误的时间。
并且还提供了一个指向较早帖子的链接,该帖子描述了如何禁用整个功能,如下所示:
...您可以通过添加以下注册表项恢复到以前的操作系统行为并全面禁用闰秒:
HKLM:\SYSTEM\CurrentControlSet\Control\LeapSecondInformation
- 类型:“REG_DWORD”
- 名称:启用
- 值:
0
禁用系统范围的设置- 值:
1
启用系统范围的设置接下来,重新启动系统。
IERS 不可预测地添加了闰秒。自 1972 年定义 UTC 和闰秒以来,增加了 23 秒。维基百科说“由于地球的自转速度从长远来看是不可预测的,因此无法提前六个月以上预测对它们的需求。”
由于您必须保留插入闰秒的历史记录,并不断更新操作系统以保留插入时间的参考,而且差异如此之小,因此不要期望通用操作系统能够补偿闰秒。
此外,与 UTC 相比,PC 中的简单电子时钟的常规时钟漂移远大于闰秒所需的补偿。如果您需要那种精度来补偿闰秒,您不应该使用高度不准确的 PC 时钟。
根据此评论,windows 完全不知道闰秒。如果将 24 * 60 * 60 秒添加到表示今天 1:39:45 的 FILETIME 中,无论如何都会得到表示明天 1:39:45 的 FILETIME。
一个非常粗略的总结:
UTC =(原子时)+(闰秒)~~(平均太阳时)
MS 文档具体说是“UTC”,因此应该包括闰秒。与 MS 一样,您的里程可能会有所不同。