将Unix/Linux时间转换为Windows FILETIME

Dix*_*eel 4 filetime

我再次从Windows转向Linux,我必须将一个从Windows移植到Linux的函数来计算NTP时间.看似简单但格式为Windows FILETIME格式.我有点想知道差异是什么,但到目前为止我无法正确地将我的Linux时间转换为Windows文件时格式.有没有人对如何做到这一点有任何想法?

我看过一些关于如何做到这一点的文章,但他们都使用win32函数,我不能使用它们!如果没有意义,我可以发布Windows代码,谢谢.

他们还花费当前时间并从1900年1月1日减去它以获得增量找到NTP,我想在Linux中我只是添加const unsigned long EPOCH = 2208988800UL到我得到这个结果的时间?

谢谢.

小智 9

FILETIME结构的Microsoft文档解释了它的含义.基本思想是Windows 从1601年1月1日开始FILETIME计算10 -7秒(100纳秒间隔)(为什么1601?不知道......).在Linux中,您可以使用从1970年1月1日起以微秒(10 -6)为单位获得时间gettimeofday().因此,以下C函数可以完成这项工作:

#include <sys/time.h>
/**
 * number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
 */
#define EPOCH_DIFF 11644473600LL

unsigned long long
getfiletime() {
    struct timeval tv;
    unsigned long long result = EPOCH_DIFF;
    gettimeofday(&tv, NULL);
    result += tv.tv_sec;
    result *= 10000000LL;
    result += tv.tv_usec * 10;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • MS Raymond Chen 的解释:[为什么 Win32 纪元是 1601 年 1 月 1 日?](https://devblogs.microsoft.com/oldnewthing/20090306-00/?p=18913):*公历以 400-年周期,1601 是 Windows NT 设计时有效的周期的第一年。换句话说,选择它是为了让数学结果更好。* (4认同)

小智 5

一、为什么是1601?因为公历每 400 年重演一次,而预言公历从 0001-01-01 开始。所以 1601 是 1980(1970,...) 之前的最后一个周期开始,这简化了计算。(哦,这就是为什么第三个千年始于 2001 年 1 月 1 日,而不是 2000年 1 月 1 日......)

要使用来自 FILETIME 的二进制分数创建类似 NTP 时间戳的内容,

  1. 移动纪元的原点,使用 LONGLONG 或 ULONGLONG 来表示 FILETIME 的刻度。
  2. 将刻度除以 10^7 得到秒数(作为商)和分数(作为余数)。如果您纯粹以无符号计算,只需除以。但是在这种情况下您不能表示负值。
  3. 将 64 位的分数(必须 >= 0)无符号乘以 1844674407371ull,即 2^64 / 10^7(四舍五入)
  4. 取乘积的高 32 位作为 NTP 时间戳的二进制小数。(您可能希望从乘积的低 32 位开始舍入。请注意,只要小数刻度严格低于 10^7,就不会发生舍入到整秒的进位。)