use chrono::{NaiveDate, NaiveDateTime, NaiveTime, Timelike};
const EXCEL_EPOCH: NaiveDate = match NaiveDate::from_ymd_opt(1899, 12, 30) {
Some(d) => d,
None => panic!("invalid Excel epoch"),
};
pub fn datetime_to_excel(dt: NaiveDateTime) -> f64 {
let days = dt.date().signed_duration_since(EXCEL_EPOCH).num_days() as f64;
let seconds = dt.time().num_seconds_from_midnight() as f64;
days + seconds / 86_400.0
}
pub fn date_to_excel(date: NaiveDate) -> f64 {
date.signed_duration_since(EXCEL_EPOCH).num_days() as f64
}
pub fn excel_to_datetime(serial: f64) -> Option<NaiveDateTime> {
let days = serial.trunc() as i64;
let frac = serial - serial.trunc();
let date = EXCEL_EPOCH.checked_add_signed(chrono::Duration::days(days))?;
let seconds = (frac * 86_400.0).round() as u32;
let time = NaiveTime::from_num_seconds_from_midnight_opt(seconds, 0)?;
Some(NaiveDateTime::new(date, time))
}
pub fn excel_to_date(serial: f64) -> Option<NaiveDate> {
let days = serial.trunc() as i64;
EXCEL_EPOCH.checked_add_signed(chrono::Duration::days(days))
}
pub fn make_datetime(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> {
let date = NaiveDate::from_ymd_opt(year, month, day)?;
let time = NaiveTime::from_hms_opt(hour, min, sec)?;
Some(NaiveDateTime::new(date, time))
}