embedded_sdmmc/filesystem/
timestamp.rs
1pub trait TimeSource {
3 fn get_timestamp(&self) -> Timestamp;
5}
6
7#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
12#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
13pub struct Timestamp {
14 pub year_since_1970: u8,
16 pub zero_indexed_month: u8,
18 pub zero_indexed_day: u8,
20 pub hours: u8,
22 pub minutes: u8,
24 pub seconds: u8,
26}
27
28impl Timestamp {
29 pub fn from_fat(date: u16, time: u16) -> Timestamp {
31 let year = 1980 + (date >> 9);
32 let month = ((date >> 5) & 0x000F) as u8;
33 let day = (date & 0x001F) as u8;
34 let hours = ((time >> 11) & 0x001F) as u8;
35 let minutes = ((time >> 5) & 0x0003F) as u8;
36 let seconds = ((time << 1) & 0x0003F) as u8;
37 Timestamp {
39 year_since_1970: (year - 1970) as u8,
40 zero_indexed_month: if month == 0 { 0 } else { month - 1 },
41 zero_indexed_day: if day == 0 { 0 } else { day - 1 },
42 hours,
43 minutes,
44 seconds,
45 }
46 }
47
48 pub fn serialize_to_fat(self) -> [u8; 4] {
51 let mut data = [0u8; 4];
52
53 let hours = (u16::from(self.hours) << 11) & 0xF800;
54 let minutes = (u16::from(self.minutes) << 5) & 0x07E0;
55 let seconds = (u16::from(self.seconds / 2)) & 0x001F;
56 data[..2].copy_from_slice(&(hours | minutes | seconds).to_le_bytes()[..]);
57
58 let year = if self.year_since_1970 < 10 {
59 0
60 } else {
61 (u16::from(self.year_since_1970 - 10) << 9) & 0xFE00
62 };
63 let month = (u16::from(self.zero_indexed_month + 1) << 5) & 0x01E0;
64 let day = u16::from(self.zero_indexed_day + 1) & 0x001F;
65 data[2..].copy_from_slice(&(year | month | day).to_le_bytes()[..]);
66 data
67 }
68
69 pub fn from_calendar(
74 year: u16,
75 month: u8,
76 day: u8,
77 hours: u8,
78 minutes: u8,
79 seconds: u8,
80 ) -> Result<Timestamp, &'static str> {
81 Ok(Timestamp {
82 year_since_1970: if (1970..=(1970 + 255)).contains(&year) {
83 (year - 1970) as u8
84 } else {
85 return Err("Bad year");
86 },
87 zero_indexed_month: if (1..=12).contains(&month) {
88 month - 1
89 } else {
90 return Err("Bad month");
91 },
92 zero_indexed_day: if (1..=31).contains(&day) {
93 day - 1
94 } else {
95 return Err("Bad day");
96 },
97 hours: if hours <= 23 {
98 hours
99 } else {
100 return Err("Bad hours");
101 },
102 minutes: if minutes <= 59 {
103 minutes
104 } else {
105 return Err("Bad minutes");
106 },
107 seconds: if seconds <= 59 {
108 seconds
109 } else {
110 return Err("Bad seconds");
111 },
112 })
113 }
114}
115
116impl core::fmt::Debug for Timestamp {
117 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
118 write!(f, "Timestamp({})", self)
119 }
120}
121
122impl core::fmt::Display for Timestamp {
123 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
124 write!(
125 f,
126 "{}-{:02}-{:02} {:02}:{:02}:{:02}",
127 u16::from(self.year_since_1970) + 1970,
128 self.zero_indexed_month + 1,
129 self.zero_indexed_day + 1,
130 self.hours,
131 self.minutes,
132 self.seconds
133 )
134 }
135}
136
137