Конвертировать время Unix / Linux в Windows FILETIME - PullRequest
4 голосов
/ 27 августа 2010

Я снова перехожу с Windows на Linux, мне нужно перенести функцию с Windows на Linux, которая рассчитывает время NTP.Кажется простым, но формат в формате Windows FILETIME.Я вроде как представляю, в чем различия, но до сих пор я не могу правильно преобразовать свое время Linux в формат времени файлов Windows.У кого-нибудь есть идеи как это сделать?

Я видел несколько статей о том, как это сделать, но все они используют функции win32, и я не могу их использовать!Я могу опубликовать код Windows, если это не имеет смысла, спасибо.

Они также берут текущее время и вычитают его с 1 января 1900 года, чтобы получить дельту для поиска NTP, я бы предположил, в Linux я просто добавляюconst unsigned long EPOCH = 2208988800UL моего времени, чтобы получить этот результат?

Спасибо.

Ответы [ 3 ]

8 голосов
/ 09 ноября 2010

Документация Microsoft для структуры FILETIME объясняет, что это такое.Основная идея заключается в том, что Windows FILETIME отсчитывает с шагом 10 -7 секунд (интервалы в 100 наносекунд) с 1 января 1601 года (почему 1601 - без понятия ...).В Linux вы можете получить время в микросекундах (10 -6 ) с 1 января 1970 года, используя 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;
}
3 голосов
/ 18 сентября 2013

Во-первых, почему 1601? Потому что Григорианский календарь повторяется каждые 400 лет, а Григорианский календарь с запуском начинается с 0001-01-01. Таким образом, 1601 был последним началом цикла до 1980 года (1970, ...), и это упрощает вычисления. (О, и именно поэтому 3-е тысячелетие началось 2001-01-01, а не 2000-01-01 ...)

Чтобы создать что-то вроде отметки времени NTP с двоичной дробью из FILETIME,

  1. Сдвиньте начало эпохи, используя LONGLONG или ULONGLONG для представляют галочки FILETIME.
  2. Сделайте деление тиков по полу на 10 ^ 7, чтобы получить секунды (как частное) и фракция (как остаток). Если вы рассчитываете чисто в неподписанном, просто делим. Но вы не можете представлять отрицательное значения в этом случае.
  3. Без знака умножьте дробь (которая должна быть> = 0) на 64 бита на 1844674407371, что составляет 2 ^ 64/10 ^ 7 (округлено)
  4. Возьмите старшие 32 бита произведения как двоичную дробь Отметка времени NTP. (Вы можете округлить с 32 младших битов продукт. Обратите внимание, что округление до полных секунд не может происходят, пока дробные тики являются строгими ниже 10 ^ 7.)
1 голос
/ 03 января 2017

Предполагается, что вы извлекаете значение метки времени из списка какого-либо сайта Вы определяете

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