Reputation: 1061
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.
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?
Upvotes: 7
Views: 21382
Reputation: 4245
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);
Upvotes: 2
Reputation: 136
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;
}
Upvotes: 12
Reputation: 51
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,
Upvotes: 5