Windows tracks time in 100ns units since January 1, 1601. Unix tracks time in 1s units since January 1, 1970. Is there an easy way to convert between them?
The Windows documentation offers a helper function to perform the conversion from time_t
to FILETIME
: It converts the units from seconds to 100ns by multiplying against the magic number 10000000, and then adds the second magic number 116444736000000000.
Is there a way to do the conversion without having to hard-code these magic numbers? Maybe somebody else has written a conversion that we can use?
Well, here’s one place: C++/WinRT.
The winrt::clock
class represents the Windows Runtime DateTime
clock, and also provides a number of helpers to convert to and from other formats. The Windows Runtime DateTime
has the same internal format as a FILETIME
, so you can treat them as basically the same thing, just in different wrapping. And since C++/WinRT represents the Windows Runtime DateTime
as a C++ std::
object, you have all of the C++ standard library facilities available.
// from Unix time to FILETIME auto datetime = winrt::clock::from_time_t(unix_time_seconds); FILETIME filetime = winrt::clock::to_file_time(datetime); // or combined into one line FILETIME filetime = winrt::clock::to_file_time( winrt::clock::from_time_t(unix_time_seconds));
And you can just run everything in reverse to go the other way.
// from FILETIME to Unix time auto datetime = winrt::clock::from_file_time(filetime); time_t unix_time_seconds = winrt::clock::to_time_t(datetime); // or combined into one line time_t unix_time_seconds = winrt::clock::to_time_t( winrt::clock::from_file_time(filetime));
Of course, once you reach the std::
, you can stop and enjoy the scenery before moving onward to your final destination.
auto datetime = winrt::clock::from_file_time(filetime); // move forward 3 minutes datetime += 3min; time_t unix_time_seconds = winrt::clock::to_time_t(datetime);
Unix time is represented in the C++ standard library as a std::
, so you can convert your Unix timestamps into a sys_time<Duration>
(or use one of the pre-made types like sys_seconds
), and then do your work in the world of C++ std::
before converting at the last moment to a Windows FILETIME
.
time_t |
|
⇵ | |
sys_time = time_point<system_clock> ⇵ DateTime = time_point<winrt::clock> |
std::chrono::time_point |
⇵ | |
FILETIME |
To get in and out of the box through the top:
// time_t to sys_seconds auto n_seconds = std::chrono::sys_seconds(std::chrono::seconds(N)); // sys_seconds to time_t auto unix_ticks = seconds.time_since_epoch().count();
To convert between sys_time
and winrt::clock
:
auto winrt = winrt::clock::from_sys(sys); auto sys = winrt::clock::to_sys(winrt);
And to get in and out through the bottom, use the to_file_time
and from_file_time
methods, as noted earlier.
There also the lesser known Julian timestamp, microseconds since 1.1.4731 BC (I think 12:00). Basically another huge fixed offset to cater for.
Used a lot in Tandem mainframe or several SQL dialects.
Is there anything in there for this?