Skip to main content

win_time_sys/
system.rs

1// Copyright (c) 2026 Mike Grier
2//! System time, and the clocks that read it ([WT-D-3]).
3//!
4//! System time is UTC wall-clock time, so unlike interrupt time it means something after a
5//! restart and on another machine -- and unlike interrupt time it is not steady: it moves when the
6//! time is set or synchronised, backwards included. Elapsed time within one boot is interrupt
7//! time's to measure.
8//!
9//! Both clocks return the same `FILETIME`, so they share one timeline and their readings compare;
10//! they differ only in how fresh the reading is. The coarse clock is as fresh as the last system
11//! clock tick. The precise clock is documented as "the highest possible level of precision
12//! (<1us)". What each costs on a given machine is `WT-1.6`'s probe to measure.
13//!
14//! [WT-D-3]: https://github.com/MikeGrier/windows-threadpool-sys/blob/main/crates/win-time-sys/DESIGN-NOTES.md#wt-d-3
15
16use core::num::NonZeroU64;
17
18use windows_sys::Win32::Foundation::FILETIME;
19use windows_sys::Win32::System::SystemInformation::{
20    GetSystemTimeAsFileTime, GetSystemTimePreciseAsFileTime,
21};
22
23use crate::clock::Clock;
24use crate::timeline::{HUNDRED_NANOSECOND_TICKS, TimePoint, Timeline};
25
26#[cfg(test)]
27mod tests;
28
29/// System time: 100 ns ticks since midnight at the start of 1 January 1601, UTC -- Windows'
30/// `FILETIME`.
31///
32/// Its points do not compare with interrupt time's, which share its unit but not its zero:
33///
34/// ```compile_fail,E0308
35/// use win_time_sys::{Clock, InterruptClock, PreciseSystemClock};
36///
37/// let _ = PreciseSystemClock.now() < InterruptClock.now();
38/// ```
39pub enum FileTime {}
40
41impl Timeline for FileTime {
42    fn ticks_per_second() -> NonZeroU64 {
43        HUNDRED_NANOSECOND_TICKS
44    }
45}
46
47/// [`FileTime`] as of the last system clock tick, through `GetSystemTimeAsFileTime`.
48#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
49pub struct CoarseSystemClock;
50
51impl Clock for CoarseSystemClock {
52    type Timeline = FileTime;
53
54    fn now(&self) -> TimePoint<FileTime> {
55        let mut time = FILETIME::default();
56        // SAFETY: the out-parameter is a live, writable local for the duration of the call.
57        unsafe { GetSystemTimeAsFileTime(&mut time) };
58        point(time)
59    }
60}
61
62/// [`FileTime`] to under a microsecond, through `GetSystemTimePreciseAsFileTime`: finer than
63/// [`CoarseSystemClock`], and its readings compare with it. `std::time::SystemTime::now` reads the
64/// same call.
65#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
66pub struct PreciseSystemClock;
67
68impl Clock for PreciseSystemClock {
69    type Timeline = FileTime;
70
71    fn now(&self) -> TimePoint<FileTime> {
72        let mut time = FILETIME::default();
73        // SAFETY: the out-parameter is a live, writable local for the duration of the call.
74        unsafe { GetSystemTimePreciseAsFileTime(&mut time) };
75        point(time)
76    }
77}
78
79/// A `FILETIME`'s two halves, as the one count they are.
80fn point(time: FILETIME) -> TimePoint<FileTime> {
81    TimePoint::from_ticks((u64::from(time.dwHighDateTime) << 32) | u64::from(time.dwLowDateTime))
82}