const DAYS_IN_MONTH: [u64; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
#[must_use]
pub(crate) fn fat_to_epoch(value: u32) -> Option<i64> {
if value == 0 {
return None;
}
let time = value & 0xFFFF;
let date = value >> 16;
let second = u64::from((time & 0x1F) * 2);
let minute = u64::from((time >> 5) & 0x3F);
let hour = u64::from((time >> 11) & 0x1F);
let day = u64::from(date & 0x1F);
let month = u64::from((date >> 5) & 0x0F);
let year = 1980 + u64::from((date >> 9) & 0x7F);
if !(1..=12).contains(&month) || !(1..=31).contains(&day) {
return None;
}
let mut days: u64 = 0;
for y in 1970..year {
days += if is_leap(y) { 366 } else { 365 };
}
for m in 1..month {
days += DAYS_IN_MONTH[(m - 1) as usize];
if m == 2 && is_leap(year) {
days += 1;
}
}
days += day - 1;
let secs = days * 86_400 + hour * 3_600 + minute * 60 + second;
i64::try_from(secs).ok()
}
fn is_leap(year: u64) -> bool {
(year % 4 == 0 && year % 100 != 0) || year % 400 == 0
}