Convert Unix/Linux time to Windows FILETIME

北慕城南 提交于 2019-11-28 01:29:43

问题


I am once again going from Windows to Linux, I have to port a function from Windows to Linux that calculates NTP time. Seems simple but the format is in Windows FILETIME format. I sort of have an idea what the differences are but so far I can not correctly convert my Linux time to the windows filetime format. Does anyone have any ideas on how to do this?

I have seen some articles on how to do this but they all use win32 functions and I can't use them! I can post the windows code if this makes no sense, thanks.

They also take the current time and subtract it from January 1st 1900 to get the delta to find NTP, I would assume in Linux I just add the const unsigned long EPOCH = 2208988800UL to my time to get this result?

Thanks.


回答1:


The Microsoft documentation for the FILETIME structure explains what it is. The basic idea is that a Windows FILETIME counts by steps of 10-7 seconds (100-nanosecond intervals) from 1 Jan 1601 (why 1601? no idea...). In Linux you can obtain time in microseconds (10-6) from 1 Jan 1970 using gettimeofday(). Thus the following C function does the job:

#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;
}



回答2:


First, why 1601? Because the Gregorian Calendar repeats itself every 400 years, and the proleptic Gregorian Calendar starts with 0001-01-01. So 1601 was the last cycle start before 1980(1970,...) and that simplifies the calculations. (Oh, and that's why the 3rd millenium started on 2001-01-01, and not on 2000-01-01...)

To create something like a NTP time stamp with a binary fraction from a FILETIME,

  1. Shift the origin of the epoch, using a LONGLONG or ULONGLONG to represent the FILETIME's ticks.
  2. Do a floor division of the ticks by 10^7 to get the seconds (as quotient) and the fraction (as the remainder). If you calculate purely in unsigned, simply divide. But you cannot represent negative values in that case.
  3. Unsigned multiply the fraction (which must be >= 0) in 64 bits by 1844674407371ull, which is 2^64 / 10^7 (rounded)
  4. Take the upper 32 bits of the product as the binary fraction of the NTP time stamp. (You might want to round from the lower 32 bits of the product. Note that a rounding carry into the full seconds cannot occur as long as the fractional ticks are strict below 10^7.)



回答3:


Assuming you fetch the timestamp value from scrapping some website. You define

unsigned __int64 timestamp = 0;

The value you fetch might need to be divided by 1000.

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

then you do as follow:

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


来源:https://stackoverflow.com/questions/3585583/convert-unix-linux-time-to-windows-filetime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!