Convert Windows Filetime to Second in Unix/Linux

Convert Windows Filetime to second in Unix/Linux

it's quite simple: the windows epoch starts 1601-01-01T00:00:00Z. It's 11644473600 seconds before the UNIX/Linux epoch (1970-01-01T00:00:00Z). The Windows ticks are in 100 nanoseconds. Thus, a function to get seconds from the UNIX epoch will be as follows:

#define WINDOWS_TICK 10000000
#define SEC_TO_UNIX_EPOCH 11644473600LL

unsigned WindowsTickToUnixSeconds(long long windowsTicks)
{
return (unsigned)(windowsTicks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
}

Convert Unix/Linux time to Windows FILETIME

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

Convert current time from windows to unix timestamp in C or C++

Maybe my question was phrased badly: All I wanted was to get the current time on a windows machine as a unix timestamp.
I now figured it out myself (C language, Code::Blocks 12.11, Windows 7 64 bit):

#include <stdio.h>
#include <time.h>
int main(int argc, char** argv) {
time_t ltime;
time(<ime);
printf("Current local time as unix timestamp: %li\n", ltime);

struct tm* timeinfo = gmtime(<ime); /* Convert to UTC */
ltime = mktime(timeinfo); /* Store as unix timestamp */
printf("Current UTC time as unix timestamp: %li\n", ltime);

return 0;
}

Example output:

Current local time as unix timestamp: 1386334692
Current UTC time as unix timestamp: 1386331092

Converting time from one environment into another in C++

Here is code to do this which was actually donated to this site by a member of the MSVC std::lib team (Billy O'Neal).

Repeated here:

// filetime_duration has the same layout as FILETIME; 100ns intervals
using filetime_duration = duration<int64_t, ratio<1, 10'000'000>>;
// January 1, 1601 (NT epoch) - January 1, 1970 (Unix epoch):
constexpr duration<int64_t> nt_to_unix_epoch{INT64_C(-11644473600)};

system_clock::time_point
FILETIME_to_system_clock(FILETIME fileTime)
{
const filetime_duration asDuration{static_cast<int64_t>(
(static_cast<uint64_t>(fileTime.dwHighDateTime) << 32)
| fileTime.dwLowDateTime)};
const auto withUnixEpoch = asDuration + nt_to_unix_epoch;
return system_clock::time_point{
duration_cast<system_clock::duration>(withUnixEpoch)};
}

This converts to system_clock::time_point, which has nanoseconds precision on Linux and 100-nanosecond precision on Windows.

Using my date/time library, it is easy to format system_clock::time_point to full precision with any format you want.

Also, here it is without using the Windows FILETIME structure:

#include "date.h"
#include <string>
#include <iostream>

std::chrono::system_clock::time_point
FILETIME_to_system_clock(std::uint64_t fileTime)
{
using namespace std;
using namespace std::chrono;
// filetime_duration has the same layout as FILETIME; 100ns intervals
using filetime_duration =duration<int64_t, ratio<1, 10000000>>;
// January 1, 1601 (NT epoch) - January 1, 1970 (Unix epoch):
constexpr duration<int64_t> nt_to_unix_epoch{INT64_C(-11644473600)};

const filetime_duration asDuration{static_cast<int64_t>(fileTime)};
const auto withUnixEpoch = asDuration + nt_to_unix_epoch;
return system_clock::time_point{
duration_cast<system_clock::duration>(withUnixEpoch)};
}

int
main()
{
std::string s = date::format("%F %T", FILETIME_to_system_clock(131400356659154460));
std::cout << s << '\n';
}

This just output for me:

2017-05-23 17:54:25.915446

Note that this is only to microseconds precision. On Linux, this will format to nanoseconds precision because system_clock::time_point has nanoseconds precision on that platform.

If that weren't the case, you could force nanosecond-precision like this:

    using namespace std::chrono;
std::string s = date::format("%F %T",
time_point_cast<nanoseconds>(FILETIME_to_system_clock(131400356659154460)));

Output for me:

2017-05-23 17:54:25.915446000

In this update the precision of the output chrono::time_point is the same as Window's FILETIME: 100-ns precision:

#include "date.h"
#include <string>
#include <iostream>

using filetime_duration = std::chrono::duration<std::int64_t, std::ratio<1, 10000000>>;
using FileTime = std::chrono::time_point<std::chrono::system_clock, filetime_duration>;
// or more simply:
// using FileTime = date::sys_time<filetime_duration>;

FileTime
FILETIME_to_system_clock(std::uint64_t fileTime)
{
using namespace std;
using namespace std::chrono;
// filetime_duration has the same layout as FILETIME; 100ns intervals
// January 1, 1601 (NT epoch) - January 1, 1970 (Unix epoch):
constexpr seconds nt_to_unix_epoch{-11644473600};

const filetime_duration asDuration{static_cast<int64_t>(fileTime)};
return FileTime{asDuration + nt_to_unix_epoch};
}

int
main()
{
using namespace std::chrono;
std::string s = date::format("%F %T", FILETIME_to_system_clock(131400356659154461));
std::cout << s << '\n';
}

Output:

2017-05-23 17:54:25.9154461

Ways to Convert Unix/Linux time to Windows time

This is described in Converting a time_t Value to a File Time, which provides sample C code.

Summary:

filetime = (unixtime * 10000000) + 116444736000000000

0x3DE43B0C → 0x01C295C4:91150E00 (2002-11-27 03:25:00 +0000)

(Also helpful is How to recognize different types of timestamps from quite a long way away.)


Often it is easier to parse the human-readable timestamp, such as "2002-11-27 03:25:00" (printf %AF %AT), using strptime() or similar.



Related Topics



Leave a reply



Submit