1use crate::CmsError;
30use crate::writer::write_u16_be;
31#[cfg(not(target_arch = "wasm32"))]
32use std::time::{SystemTime, UNIX_EPOCH};
33
34#[repr(C)]
35#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
36pub struct ColorDateTime {
37 pub year: u16,
38 pub month: u16,
39 pub day_of_the_month: u16,
40 pub hours: u16,
41 pub minutes: u16,
42 pub seconds: u16,
43}
44
45fn is_leap(year: i32) -> bool {
46 (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
47}
48
49fn days_in_month(year: i32, month: i32) -> i32 {
50 match month {
51 1 => 31,
52 2 => {
53 if is_leap(year) {
54 29
55 } else {
56 28
57 }
58 }
59 3 => 31,
60 4 => 30,
61 5 => 31,
62 6 => 30,
63 7 => 31,
64 8 => 31,
65 9 => 30,
66 10 => 31,
67 11 => 30,
68 12 => 31,
69 _ => unreachable!("Unknown month"),
70 }
71}
72
73impl Default for ColorDateTime {
74 fn default() -> Self {
75 Self::now()
76 }
77}
78
79impl ColorDateTime {
80 pub fn new_from_slice(slice: &[u8]) -> Result<ColorDateTime, CmsError> {
82 if slice.len() != 12 {
83 return Err(CmsError::InvalidProfile);
84 }
85 let year = u16::from_be_bytes([slice[0], slice[1]]);
86 let month = u16::from_be_bytes([slice[2], slice[3]]);
87 let day_of_the_month = u16::from_be_bytes([slice[4], slice[5]]);
88 let hours = u16::from_be_bytes([slice[6], slice[7]]);
89 let minutes = u16::from_be_bytes([slice[8], slice[9]]);
90 let seconds = u16::from_be_bytes([slice[10], slice[11]]);
91 Ok(ColorDateTime {
92 year,
93 month,
94 day_of_the_month,
95 hours,
96 minutes,
97 seconds,
98 })
99 }
100
101 pub fn now() -> Self {
103 #[cfg(not(target_arch = "wasm32"))]
104 let now = match SystemTime::now().duration_since(UNIX_EPOCH) {
105 Ok(v) => v,
106 Err(_) => return Self::default(),
107 };
108 #[cfg(target_arch = "wasm32")]
109 use std::time::Duration;
110 #[cfg(target_arch = "wasm32")]
111 let now = Duration::new(365 * 60 * 60 * 24 * 30, 0);
112 let mut days = (now.as_secs() / 86_400) as i64;
113 let secs_of_day = (now.as_secs() % 86_400) as i64;
114
115 let mut year = 1970;
116 loop {
117 let year_days = if is_leap(year) { 366 } else { 365 };
118 if days >= year_days {
119 days -= year_days;
120 year += 1;
121 } else {
122 break;
123 }
124 }
125
126 let mut month = 1;
127 loop {
128 let mdays = days_in_month(year, month);
129 if days >= mdays as i64 {
130 days -= mdays as i64;
131 month += 1;
132 } else {
133 break;
134 }
135 }
136 let day = days + 1; let hour = secs_of_day / 3600;
139 let min = (secs_of_day % 3600) / 60;
140 let sec = secs_of_day % 60;
141 Self {
142 year: year as u16,
143 month: month as u16,
144 day_of_the_month: day as u16,
145 hours: hour as u16,
146 minutes: min as u16,
147 seconds: sec as u16,
148 }
149 }
150
151 #[inline]
152 pub(crate) fn encode(&self, into: &mut Vec<u8>) {
153 let year = self.year;
154 let month = self.month;
155 let day_of_the_month = self.day_of_the_month;
156 let hours = self.hours;
157 let minutes = self.minutes;
158 let seconds = self.seconds;
159 write_u16_be(into, year);
160 write_u16_be(into, month);
161 write_u16_be(into, day_of_the_month);
162 write_u16_be(into, hours);
163 write_u16_be(into, minutes);
164 write_u16_be(into, seconds);
165 }
166}