keramics_datetime/
filetime.rs1use std::fmt;
15
16use keramics_types::bytes_to_u32_le;
17
18use super::epoch::Epoch;
19use super::util::{get_date_values, get_time_values};
20
21const FILETIME_EPOCH: Epoch = Epoch {
22 year: 1601,
23 month: 1,
24 day_of_month: 1,
25};
26
27#[derive(Clone, Debug, Default, PartialEq)]
29pub struct Filetime {
30 pub timestamp: u64,
32}
33
34impl Filetime {
35 pub fn new(timestamp: u64) -> Self {
37 Self {
38 timestamp: timestamp,
39 }
40 }
41
42 pub fn from_bytes(data: &[u8]) -> Self {
47 let lower_32bit: u32 = bytes_to_u32_le!(data, 0);
48 let upper_32bit: u32 = bytes_to_u32_le!(data, 4);
49 Self {
50 timestamp: (upper_32bit as u64) << 32 | (lower_32bit as u64),
51 }
52 }
53
54 pub fn to_iso8601_string(&self) -> String {
56 let fraction: u64 = self.timestamp % 10000000;
57 let number_of_seconds: u64 = self.timestamp / 10000000;
58 let (days, hours, minutes, seconds): (i64, u8, u8, u8) =
59 get_time_values(number_of_seconds as i64);
60 let (year, month, day_of_month): (i16, u8, u8) = get_date_values(days, &FILETIME_EPOCH);
61 format!(
62 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:07}",
63 year, month, day_of_month, hours, minutes, seconds, fraction
64 )
65 }
66}
67
68impl fmt::Display for Filetime {
69 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
71 write!(
72 formatter,
73 "{} (0x{:08x}:0x{:08x})",
74 self.to_iso8601_string(),
75 self.timestamp >> 32,
76 self.timestamp & 0xffffffff,
77 )
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_filetime_from_bytes() {
87 let test_data: [u8; 8] = [0xce, 0x17, 0x0a, 0x3d, 0x62, 0x3a, 0xcb, 0x01];
88
89 let test_struct: Filetime = Filetime::from_bytes(&test_data);
90 assert_eq!(test_struct.timestamp, 0x01cb3a623d0a17ce);
91 }
92
93 #[test]
94 fn test_filetime_to_iso8601_string() {
95 let test_struct: Filetime = Filetime::new(0x01cb3a623d0a17ce);
96
97 let string: String = test_struct.to_iso8601_string();
98 assert_eq!(string.as_str(), "2010-08-12T21:06:31.5468750");
99 }
100}