aboutsummaryrefslogtreecommitdiff
path: root/src/zip/datetime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip/datetime.rs')
-rw-r--r--src/zip/datetime.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/zip/datetime.rs b/src/zip/datetime.rs
new file mode 100644
index 0000000..a4b1b55
--- /dev/null
+++ b/src/zip/datetime.rs
@@ -0,0 +1,45 @@
1use crate::zip::{ZipError, ZipResult};
2use chrono::{DateTime, Datelike, NaiveDate, TimeZone, Timelike};
3
4pub trait DosDateTime<Tz>: Sized {
5 fn from_dos_date_time(date: u16, time: u16, tz: Tz) -> ZipResult<Self>;
6
7 #[allow(dead_code)]
8 fn to_dos_date(&self) -> u16;
9
10 fn to_dos_time(&self) -> u16;
11}
12
13impl<Tz: TimeZone> DosDateTime<Tz> for DateTime<Tz> {
14 #[inline]
15 fn from_dos_date_time(date: u16, time: u16, tz: Tz) -> ZipResult<Self> {
16 Ok(NaiveDate::from_ymd_opt(
17 (date as i32 >> 9 & 0x7F) + 1980,
18 date as u32 >> 5 & 0xF,
19 date as u32 & 0x1F,
20 )
21 .ok_or(ZipError::InvalidDate)?
22 .and_hms_opt(
23 (time as u32 >> 11) & 0x1F,
24 (time as u32 >> 5) & 0x3F,
25 (time as u32 & 0x1F) * 2,
26 )
27 .ok_or(ZipError::InvalidTime)?
28 .and_local_timezone(tz)
29 .unwrap())
30 }
31
32 #[inline]
33 fn to_dos_date(&self) -> u16 {
34 (self.year() as u16 - 1980 & 0x7F) << 9
35 | (self.month() as u16 & 0xF) << 5
36 | self.day() as u16 & 0x1F
37 }
38
39 #[inline]
40 fn to_dos_time(&self) -> u16 {
41 (self.hour() as u16 & 0x1F) << 11
42 | (self.minute() as u16 & 0x3F) << 5
43 | self.second() as u16 / 2 & 0x1F
44 }
45}