rustytoken/src/datetime.rs

125 lines
3.0 KiB
Rust

// This code was extracted from http://git.musl-libc.org/cgit/musl/tree/src/time?h=v0.9.15
pub struct Datetime {
pub year: u16,
pub month: u8,
pub day: u8,
pub hours: u8,
pub minutes: u8,
pub seconds: u8,
}
impl Datetime {
pub fn unix_epoch(&self) -> u64 {
let year: i64 = self.year as i64 - 1900;
let month: i64 = self.month as i64 - 1;
let (mut t, is_leap) = year_to_secs(year);
t += month_to_secs(month, is_leap);
t += 86400 * (self.day as i64 - 1);
t += 3600 * self.hours as i64;
t += 60 * self.minutes as i64;
t += self.seconds as i64;
t as u64
}
pub fn from_ds3231<T: ds323x::Rtcc>(rtc: &mut T) -> Self {
let year = rtc.year().map_err(|_| ()).unwrap();
let month = rtc.month().map_err(|_| ()).unwrap();
let day = rtc.day().map_err(|_| ()).unwrap();
let hours = match rtc.hours().map_err(|_| ()).unwrap() {
ds323x::Hours::AM(val) => val,
ds323x::Hours::PM(val) => val + 12,
ds323x::Hours::H24(val) => val,
};
let minutes = rtc.minutes().map_err(|_| ()).unwrap();
let seconds = rtc.seconds().map_err(|_| ()).unwrap();
Datetime {
year,
month,
day,
hours,
minutes,
seconds,
}
}
}
fn year_to_secs(year: i64) -> (i64, bool) {
let is_leap: bool;
let res: i64;
let mut cycles: i64;
let centuries: i64;
let mut leaps: i64;
let mut rem: i64;
cycles = (year - 100) / 400;
rem = (year - 100) % 400;
if rem < 0 {
cycles -= 1;
rem += 400;
}
if rem == 0 {
is_leap = true;
centuries = 0;
leaps = 0;
} else {
if rem >= 200 {
if rem >= 300 {
centuries = 3;
rem -= 300;
} else {
centuries = 2;
rem -= 200;
}
} else {
if rem >= 100 {
centuries = 1;
rem -= 100;
} else {
centuries = 0;
}
}
if rem == 0 {
is_leap = false;
leaps = 0;
} else {
leaps = rem / 4;
rem %= 4;
is_leap = rem == 0;
}
}
leaps += 97 * cycles + 24 * centuries - (is_leap as i64);
res = (year - 100) * 31536000 + leaps * 86400 + 946684800 + 86400;
(res, is_leap)
}
fn month_to_secs(month: i64, is_leap: bool) -> i64 {
const SECS_THROUGH_MONTH: [i64; 12] = [
0, // Jan
31 * 86400, // Feb
59 * 86400, // Mar
90 * 86400, // Apr
120 * 86400, // May
151 * 86400, // Jun
181 * 86400, // Jul
212 * 86400, // Aug
243 * 86400, // Sep
273 * 86400, // Oct
304 * 86400, // Nov
334 * 86400, // Dec
];
let mut t = SECS_THROUGH_MONTH[month as usize];
if is_leap && month >= 2 {
t += 86400;
}
t
}