将Unix / Linux时间转换为Windows FILETIME

时间:2010-08-27 15:15:23

标签: filetime

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

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

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

感谢。

3 个答案:

答案 0 :(得分:8)

FILETIME结构的Microsoft文档解释了它的含义。基本思想是Windows FILETIME从1601年1月1日起以10 -7 秒(100纳秒间隔)的步长计算(为什么1601?不知道......)。在Linux中,您可以使用gettimeofday()从1970年1月1日起以微秒(10 -6 )获得时间。因此,以下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;
}

答案 1 :(得分:3)

首先,为什么1601?因为公历每400年重复一次,而公历日历从0001-01-01开始。所以1601是1980年之前的最后一个循环开始(1970年......),这简化了计算。 (哦,这就是为什么第三个千年在2001-01-01开始,而在2000-01-01 ......)

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

  1. 使用LONGLONG或ULONGLONG来移动纪元的起源 代表FILETIME的标记。
  2. 将刻度线的分区除以10 ^ 7得到秒数(如 商)和分数(作为余数)。如果算一算 纯粹是无符号的,简单地划分。但你不能代表负面 在这种情况下的价值。
  3. 无符号乘以64位的分数(必须> = 0) 1844674407371ull,这是2 ^ 64/10 ^ 7(圆形)
  4. 将产品的高32位作为二进制分数 NTP时间戳。 (您可能希望从低32位舍入 产品。请注意,圆整进入完整的秒数不能 只要分数刻度严格低于10 ^ 7就会发生。)

答案 2 :(得分:1)

假设您从废弃某个网站获取时间戳值。你定义

unsigned __int64 timestamp = 0;

您获取的值可能需要除以1000。

if (element.HasMember(L"timestamp"))
{
    timestamp = element[L"timestamp"].GetUint64() / 1000;
}                                       }

然后你这样做:

LONGLONG ll;
ll = Int32x32To64(timestamp, 10000000) + 116444736000000000;
FILETIME ft;
ft.dwLowDateTime = (DWORD)ll;
ft.dwHighDateTime = ll >> 32;
SYSTEMTIME stTime;
FileTimeToSystemTime(&ft, &stTime);