1pub mod builder;
5
6#[cfg(feature = "jiff")]
7use jiff::{civil, tz::Offset, Timestamp};
8
9use self::builder::ZipDateTimeBuilder;
10
11#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
16pub struct ZipDateTime {
17 pub(crate) date: u16,
18 pub(crate) time: u16,
19}
20
21impl Default for ZipDateTime {
22 fn default() -> Self {
23 ZipDateTimeBuilder::new().year(1980).month(1).day(1).build()
24 }
25}
26
27impl ZipDateTime {
28 pub fn default_for_write() -> Self {
30 #[cfg(feature = "jiff")]
31 {
32 Self::from_jiff(&Offset::UTC.to_datetime(Timestamp::now()))
33 }
34
35 #[cfg(not(feature = "jiff"))]
36 {
37 Self::default()
38 }
39 }
40
41 pub fn year(&self) -> i32 {
43 (((self.date & 0xFE00) >> 9) + 1980).into()
44 }
45
46 pub fn month(&self) -> u32 {
48 ((self.date & 0x1E0) >> 5).into()
49 }
50
51 pub fn day(&self) -> u32 {
53 (self.date & 0x1F).into()
54 }
55
56 pub fn hour(&self) -> u32 {
58 ((self.time & 0xF800) >> 11).into()
59 }
60
61 pub fn minute(&self) -> u32 {
63 ((self.time & 0x7E0) >> 5).into()
64 }
65
66 pub fn second(&self) -> u32 {
70 ((self.time & 0x1F) << 1).into()
71 }
72
73 #[cfg(feature = "jiff")]
77 pub fn as_jiff(&self) -> Result<civil::DateTime, jiff::Error> {
78 self.try_into()
79 }
80
81 #[cfg(feature = "jiff")]
85 pub fn from_jiff(date_time: &civil::DateTime) -> Self {
86 date_time.into()
87 }
88}
89
90impl From<ZipDateTimeBuilder> for ZipDateTime {
91 fn from(builder: ZipDateTimeBuilder) -> Self {
92 builder.0
93 }
94}
95
96#[cfg(feature = "jiff")]
97impl From<&civil::DateTime> for ZipDateTime {
98 fn from(value: &civil::DateTime) -> Self {
99 let mut builder = ZipDateTimeBuilder::new();
100
101 builder = builder.year(value.year().into());
102 builder = builder.month(value.month() as u32);
103 builder = builder.day(value.day() as u32);
104 builder = builder.hour(value.hour() as u32);
105 builder = builder.minute(value.minute() as u32);
106 builder = builder.second(value.second() as u32);
107
108 builder.build()
109 }
110}
111
112#[cfg(feature = "jiff")]
113impl TryFrom<&ZipDateTime> for civil::DateTime {
114 type Error = jiff::Error;
115
116 fn try_from(value: &ZipDateTime) -> Result<Self, Self::Error> {
117 Self::new(
118 value.year() as i16,
119 value.month() as i8,
120 value.day() as i8,
121 value.hour() as i8,
122 value.minute() as i8,
123 value.second() as i8,
124 0,
125 )
126 }
127}
128
129#[cfg(feature = "jiff")]
130impl From<civil::DateTime> for ZipDateTime {
131 fn from(value: civil::DateTime) -> Self {
132 (&value).into()
133 }
134}
135
136#[cfg(feature = "jiff")]
137impl TryFrom<ZipDateTime> for civil::DateTime {
138 type Error = jiff::Error;
139
140 fn try_from(value: ZipDateTime) -> Result<Self, Self::Error> {
141 (&value).try_into()
142 }
143}