Windows FILETIME 结构是否包含闰秒?

发布于 2024-07-06 06:22:19 字数 185 浏览 12 评论 0原文

FILETIME 结构 根据 Microsoft 文档,从 1601 年 1 月 1 日(大概是当天开始)算起,但这包括闰秒吗?

The FILETIME structure counts from January 1 1601 (presumably the start of that day) according to the Microsoft documentation, but does this include leap seconds?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

垂暮老矣 2024-07-13 06:22:19

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

它应该是:

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

简单的答案是“不”。 FileTimeToSystemTime 将秒返回为 0..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.ED

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

The question shouldn't be if FILETIME includes leap seconds.

It should be:

Do the people, functions, and libraries, who interpret a FILETIME (i.e. FileTimeToSystemTime) include leap seconds when counting the duration?

The simple answer is "no". FileTimeToSystemTime returns seconds as 0..59.


The simpler answer is: "of course not, how could it?".

My Windows 2000 machine doesn't know that there were 2 leap seconds added in the decade since it was released. Any interpretation it makes of a FILETIME is wrong.


Finally, rather than relying on logic, we can determine by direct experimental observation, the answer to the posters question:

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

Adding one second to

12/31/2008 11:59:59pm

gives

1/1/2009 12:00:00am

rather than

1/1/2009 11:59:60pm

Q.E.D.

Original poster might not like it, but god intentionally rigged it so that a year is not evenly divisible by a day. He did it just to screw up programmers.

凉栀 2024-07-13 06:22:19

如果不先确定:Windows FILETIME 实际计算的是多少,则这个问题不可能有唯一的答案。 微软文档说它计算自 1601 UTC 以来的 100 纳秒间隔,但这是有问题的。

1960 年之前不存在任何形式的国际协调时间。1964 年之前的任何文献中都没有出现过 UTC 这个名称。UTC 作为官方名称直到 1970 年才存在。但情况变得更糟。 皇家格林威治天文台直到 1676 年才建立,因此即使尝试将 FILETIME 解释为 GMT 也没有明确的含义,直到那时,带有精确擒纵机构的摆钟才开始提供 1 秒的精度。

如果 FILETIME 被解释为平均太阳秒,则自 1601 年以来的闰秒数为零,因为 UT 没有闰秒。 如果 FILETIME 被解释为好像存在原子天文钟,那么自 1601 年以来的闰秒数约为 -60(即负 60 闰秒)。

那是古老的历史,那么自从原子天文钟以来的时代呢? 这也好不到哪儿去,因为各国政府还没有区分平太阳秒和国际单位秒。 十年来,ITU-R一直在讨论放弃闰秒,但尚未达成国际共识。 部分原因可见于
此页面上的 javascript (另请参阅该页面上的 delta-T 链接古代历史的情节)。 由于各国政府尚未做出明确区分,因此根据某些司法管辖区的法律,自 1972 年以来定义秒数的任何尝试都面临着无效的风险。 ITU-R 的代表以及 POSIX 委员会的人员都意识到这种复杂性。 在外交问题得到解决之前,在各国政府和国际标准对平均太阳秒和国际单位秒之间做出明确区分和选择之前,计算机标准几乎没有希望效仿。

There can be no single answer to this question without first deciding: What is the Windows FILETIME actually counting? The Microsoft docs say it counts 100 nanosecond intervals since 1601 UTC, but this is problematic.

No form of internationally coordinated time existed prior to the year 1960. The name UTC itself does not occur in any literature prior to 1964. The name UTC as an official designation did not exist until 1970. But it gets worse. The Royal Greenwich Observatory was not established until 1676, so even trying to interpret the FILETIME as GMT has no clear meaning, and it was only around then that pendulum clocks with accurate escapements began to give accuracies of 1 second.

If FILETIME is interpreted as mean solar seconds then the number of leap seconds since 1601 is zero, for UT has no leap seconds. If FILETIME is interpreted as if there had been atomic chronometers then the number of leap seconds since 1601 is about -60 (that's negative 60 leap seconds).

That is ancient history, what about the era since atomic chronometers? It is no better because national governments have not made the distinction between mean solar seconds and SI seconds. For a decade the ITU-R has been discussing abandoning leap seconds, but they have not achieved international consensus. Part of the reason for that can be seen in the
javascript on this page (also see the delta-T link on that page for plots of the ancient history). Because national governments have not made a clear distinction, any attempt to define the count of seconds since 1972 runs the risk of being invalid according to the laws of some jurisdiction. The delegates to ITU-R are aware of this complexity, as are the folks on the POSIX committee. Until the diplomatic issues are worked out, until national governments and international standards make a clear distinction and choice between mean solar and SI seconds, there is little hope that the computer standards can follow suit.

岁月静好 2024-07-13 06:22:19

此处详细介绍了为何选择该特定日期。

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

公历的运行依据是
400年一个周期,1601年是第一个
周期的活跃年份
Windows NT 的时代
设计的。 换句话说,它是
选择让数学出来
很好。

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

Here's some more info about why that particular date was chosen.

The FILETIME structure records time in
the form of 100-nanosecond intervals
since January 1, 1601. Why was that
date chosen?

The Gregorian calendar operates on a
400-year cycle, and 1601 is the first
year of the cycle that was active at
the time Windows NT was being
designed. In other words, it was
chosen to make the math come out
nicely.

I actually have the email from Dave
Cutler confirming this.

寄意 2024-07-13 06:22:19

这个问题的答案过去是否定的,但已更改为:是的,有点,有时...

根据Windows 网络团队博客文章

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

由于自添加此功能以来尚未发出闰秒,因此操作系统仍然不知道任何闰秒。 然而,当下一个官方闰秒出现时,启用了此新功能的 Windows 计算机将跟踪它,因此 FILETIME 值将根据闰秒数进行偏移。解释它们时的计算机。

该博客文章继续描述:

未对 FILETIME 进行任何更改。 它仍然表示自纪元开始以来 100 ns 间隔的数量。 改变的是该数字在 SYSTEMTIME 和反之之间转换时的解释。 以下是受影响的 API 列表:

  • 获取系统时间
  • 获取本地时间
  • 文件时间到系统时间
  • 文件时间到本地时间
  • 系统时间到文件时间
  • 设置系统时间
  • 设置本地时间

在此版本之前,SYSTEMTIME 的 wSecond 有效值在 0 到 59 之间。SYSTEMTIME 现在已更新为允许值 60,前提是年、月和日代表闰秒有效的日期。< /p>

...

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

请注意,选择加入适用于列出的函数内的行为,该函数列出了如何将FILETIME映射到SYSTEMTIME。 无论您是否选择加入,操作系统仍会根据其识别的闰秒来偏移 FILETIME 值。

关于兼容性,文章指出:

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

还提供了早期帖子的链接 描述了如何禁用整个功能,如下:

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

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

接下来,重新启动系统。

The answer to this question used to be no, but has changed to: YES, sort of, sometimes...

Per the Windows Networking team blog article:

Starting in Server 2019 and the Windows 10 October [2018] update time APIs will now take into account all leap seconds the Operating System is aware of when it translates FILETIME to SystemTime.

As there have been no leap seconds issued since the time of this feature being added, the operating system is still unaware of any leap seconds. However, when the next official leap second makes its way into the world, Windows computers that have this new feature enabled will keep track of it, and thus FILETIME values will be offset by the number of leap seconds on the computer at the time they are interpreted.

The blog post goes on to describe:

No change is made to FILETIME. It still represents the number of 100 ns intervals since the start of the epoch. What has changed is the interpretation of that number when it is converted to SYSTEMTIME and back. Here is a list of affected APIs:

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

Previous to this release, SYSTEMTIME had valid values for wSecond between 0 and 59. SYSTEMTIME has now been updated to allow a value of 60, provided the year, month, and day represents day in which a leap second is valid.

...

In order receive the 60 second in the SYSTEMTIME structure a process must explicitly opt-in.

Note that the opt-in applies to the behavior within the functions listed on how a FILETIME is mapped to a SYSTEMTIME. Regardless of whether you opt-in or not, the operating system will still offset FILETIME values according to the leap seconds it is aware of.

With regard to compatibility, the article states:

Applications that rely on 3rd party frameworks should ensure their framework’s implementation on Windows is also calling into the correct APIs to calculate the correct time, or else the application will have the wrong time reported.

And also provides a links to an earlier post which describes how to disable the entire feature, as follows:

... you can revert to the prior operating system behavior and disable leap seconds across the board by adding the following registry key:

  • HKLM:\SYSTEM\CurrentControlSet\Control\LeapSecondInformation
  • Type: "REG_DWORD"
  • Name: Enabled
  • Value: 0 Disables the system-wide setting
  • Value: 1 Enables the system-wide setting

Next, restart your system.

无畏 2024-07-13 06:22:19

IERS 会不可预测地添加闰秒。 自 1972 年定义 UTC 和闰秒以来,增加了 23 秒。 维基百科称“由于从长远来看,地球的自转速度是不可预测的,因此不可能提前六个月以上预测对它们的需求。”

由于您必须保留插入闰秒的历史记录,并不断更新操作系统以保留插入闰秒的参考,并且差异如此之小,因此不期望通用操作系统能够补偿闰秒。

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

Leap seconds are added unpredictably by the IERS. 23 seconds have been added since 1972, when UTC and leap seconds were defined. Wikipedia says "because the Earth's rotation rate is unpredictable in the long term, it is not possible to predict the need for them more than six months in advance."

Since you'd have to keep a history of when leap seconds were inserted, and keep updating the OS to keep a reference of when they had been inserted, and the difference is so small, it's fair not to expect a general-purpose OS to compensate for leap seconds.

In addition, regular clock drift, of the simple electronic clock in your PC compared to UTC, is so much larger than the compensation required for leap seconds. If you need the kind of precision to compensate for leap seconds, you shouldn't use the highly-inaccurate PC clock.

不顾 2024-07-13 06:22:19

根据这个 评论 windows 完全不知道闰秒。 如果您将 24 * 60 * 60 秒添加到代表今天 1:39:45 的 FILETIME 中,无论如何,您都会得到代表明天 1:39:45 的 FILETIME。

According to this comment windows is totally unaware of leap seconds. If you add 24 * 60 * 60 seconds to a FILETIME that represents 1:39:45 today, you get a FILETIME that represents 1:39:45 tomorrow, no matter what.

蓝眸 2024-07-13 06:22:19

一个非常粗略的总结:

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

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

A very crude summary:

UTC = (Atomic Time) + (Leap Seconds) ~~ (Mean Solar Time)

The MS documentation says, specifically, "UTC", and so should include the leap seconds. As always with MS, your mileage may vary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文