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