1use std::time::{Duration, SystemTime};
2
3#[allow(non_snake_case)]
4#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
5pub struct FILETIME {
6 pub dwLowDateTime: u32,
7 pub dwHighDateTime: u32,
8}
9
10impl FILETIME {
11 const MS_EPOCH: u64 = 11_6444_7360_0000_0000;
12
13 #[inline]
14 pub fn now() -> Self {
15 SystemTime::now().into()
16 }
17
18 pub fn into_systime(self) -> Option<SystemTime> {
19 let FILETIME { dwLowDateTime: low, dwHighDateTime: high } = self;
20 let ftime = ((high as u64) << 32) | low as u64;
21 let nanos = (ftime.checked_sub(Self::MS_EPOCH)?) * 100;
22 Some(SystemTime::UNIX_EPOCH + Duration::from_nanos(nanos))
23 }
24}
25
26impl From<SystemTime> for FILETIME {
27 fn from(time: SystemTime) -> Self {
28 let duration = time.duration_since(SystemTime::UNIX_EPOCH).unwrap();
29 let ftime = (duration.as_nanos() / 100) as u64 + Self::MS_EPOCH;
30 FILETIME { dwLowDateTime: ftime as u32, dwHighDateTime: (ftime >> 32) as u32 }
31 }
32}
33
34#[test]
35fn test_convert_roundtrip() {
36 let now = SystemTime::now();
37 let ftime = FILETIME::from(now);
38 let round_trip = ftime.into_systime().unwrap();
39 assert_eq!(
43 now.duration_since(SystemTime::UNIX_EPOCH)
44 .as_ref()
45 .map(Duration::as_nanos)
46 .map(|nanos| nanos / 100)
47 .unwrap(),
48 round_trip
49 .duration_since(SystemTime::UNIX_EPOCH)
50 .as_ref()
51 .map(Duration::as_nanos)
52 .map(|nanos| nanos / 100)
53 .unwrap()
54 );
55}