diff options
Diffstat (limited to 'src/zip/datetime.rs')
| -rw-r--r-- | src/zip/datetime.rs | 45 |
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 @@ | |||
| 1 | use crate::zip::{ZipError, ZipResult}; | ||
| 2 | use chrono::{DateTime, Datelike, NaiveDate, TimeZone, Timelike}; | ||
| 3 | |||
| 4 | pub 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 | |||
| 13 | impl<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 | } | ||
