October 1st, 2025
likeheart2 reactions

How do I convert a FILETIME to a C++ clock like std::system_clock or winrt::clock?

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_cast<winrt::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;
 
Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Sort by :
  • Grant Shirreffs · Edited
    auto to_system_clock(const FILETIME& ft)
    {
    	std::chrono::file_clock::duration d{ (static_cast<int_64>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime };
    	std::chrono::file_clock::time_point tp(d);
    	return std::chrono::clock_cast<std::chrono::system_clock>(tp);
    }
    

    Or am I missing something?

    Note: the MSVC implementation of this won’t work on Server 2019, as icu.dll is missing on that installation. Somehow this is not regarded as a bug.