The traditional Win32 data structure for holding a date/time is the FILETIME. How do you interoperate between this and the C++ clocks like std::system_clock and winrt::clock?

When C++ introduced the concept of clocks in C++11, it did not require clocks to have any particular epoch. In C++20, the rules were strengthened to require system_clock to have an epoch of January 1, 1970 (so-called Unix Time). The period of the system clock remains unspecified, although you can inspect it at compile time via std::chrono::system_clock::period.

So how do you get a FILETIME into a C++ clock?

C++/WinRT’s winrt::clock comes to the rescue. This is the projection of the Windows Runtime DateTime structure, which is defined to be in the same units as FILETIME. Therefore, once you pack the two parts of the FILETIME into a single int64_t, the conversion between FILETIME and winrt::clock is mathematically trivial.

It’s mathematically trivial, but you still have to do a bunch of typing:

winrt::clock::time_point winrt_clock_from_FILETIME(FILETIME ft) { // First, pack it into a 64-bit integer auto count = (static_cast<long long>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;

// Then place it inside a duration (aka TimeSpan) to represent
/  time since epoch
auto span = winrt::clock::duration(count);
// Alternatively: auto span = winrt::Windows::Foundation::TimeSpan(count);

// Then create a winrt::clock::time_point from it   
return winrt::clock::time_point(span);
// Alternatively: return winrt::Windows::Foundation::DateTime(span);

}

Fortunately, C++/WinRT comes with helpers to make this easier.

For example, the winrt::file_time structure lets you convert between FILETIME and 64-bit integers.

winrt::clock::time_point winrt_clock_from_FILETIME(FILETIME ft) { // First, pack it into a 64-bit integer auto count = winrt::file_time(ft).value;

// Then place it inside a duration (aka TimeSpan) to represent
/  time since epoch
auto span = winrt::clock::duration(count);
// Alternatively: auto span = winrt::Windows::Foundation::TimeSpan(count);

// Then create a winrt::clock::time_point from it   
return winrt::clock::time_point(span);
// Alternatively: return winrt::Windows::Foundation::DateTime(span);

}

And the conversion to a duration, and then to a time point is handled by another helper:

winrt::clock::time_point winrt_clock_from_FILETIME(FILETIME ft) { auto t = winrt::file_time(ft); return winrt::clock::from_file_time(t); }

And the entire thing is handled by yet another helper:

winrt::clock::time_point winrt_clock_from_FILETIME(FILETIME ft) { return winrt::clock::from_FILETIME(ft); }

So we didn’t need to write our function at all. C++/WinRT came with it built-in.

Once you’ve entered C+±land, you can use a clock cast to convert it to other C++ clocks.

template<typename Clock> typename Clock::time_point clock_from_FILETIME(FILETIME ft) { return std::chrono::clock_cast<Clock>( winrt::clock::from_FILETIME(ft)); }

template<typename TimePoint> FILETIME FILETIME_from_clock(TimePoint const& t) { return winrt::clock::to_FILETIME( std::chrono::clock_castwinrt::clock(t));
}

Bonus reading: Converting between Windows FILETIME and Unix time_t without having to type the magic number 116444736000000000. The winrt::clock also gets you out of the constants business.

magic1 = winrt::clock::from_time_t(0).time_since_epoch().count(); magic2 = winrt::clock::period::num / winrt::clock::period::den;

The post How do I convert a <CODE>FILETIME</CODE> to a C++ clock like <CODE>std::system_clock</CODE> or <CODE>winrt::clock</CODE>? appeared first on The Old New Thing.


From The Old New Thing via this RSS feed