use super::{DateTime, TimeZone}; pub const SECS_PER_DAY: i64 = 86400; fn days_since_epoch(ts: i64) -> i64 { ts / SECS_PER_DAY } fn is_leap(year: i64) -> bool { year % 4 == 0 && (year % 100 != 0 || year % 16 == 0) } fn year_from_ts_with_remainder(ts: i64) -> (i64, i64) { let mut year = 1970; let mut days = days_since_epoch(ts); loop { let days_in_year = if is_leap(year) { 366 } else { 365 }; if days > days_in_year { days -= days_in_year; year += 1; } else { break; } } (year, days) } fn days_in_month(month: u8, year: i64) -> i64 { assert!(month < 13); match month { 1 | 3 | 5 | 7 | 10 | 12 => 31, 2 => { if is_leap(year) { 29 } else { 28 } }, 4 | 6 | 9 | 11 => 30, _ => unreachable!(), } } fn month_and_days_from_ordinal(days: i64, year: i64) -> (u8, i64) { assert!( if is_leap(year) { days < 366 } else { days < 365 } ); let mut days = days; let mut month = 1; while days_in_month(month, year) <= days { days -= days_in_month(month, year); month += 1; } (month, days) } pub(super) fn date_time_from_ts(ts: i64) -> DateTime { let (year, days) = year_from_ts_with_remainder(ts); let (month, days) = month_and_days_from_ordinal(days, year); let seconds = ts % SECS_PER_DAY; println!("Seconds: {seconds}"); let minutes = seconds / 60; println!("Minutes: {minutes}"); let second = seconds % 60; let hour = minutes / 60; let minute = minutes % 60; DateTime { year: year as u32, month: month.try_into().unwrap(), day: (days + 1).try_into().unwrap(), hour: Some((hour + 1).try_into().unwrap()), minute: Some((minute).try_into().unwrap()), second: Some(second.try_into().unwrap()), tz: Some(TimeZone::UTC), } } #[cfg(test)] mod tests { use super::*; #[test] fn get_year() { let ts = 1686459092; let (y, r) = year_from_ts_with_remainder(ts); assert_eq!(y, 2023); assert_eq!(r, 161); } #[test] fn get_month_and_days() { let ts = 1686459092; let (year, days) = year_from_ts_with_remainder(ts); let (month, days) = month_and_days_from_ordinal(days, year); assert_eq!(month, 6); assert_eq!(days, 10); } #[test] fn get_datetime() { let ts = 1686462068; let dt = date_time_from_ts(ts); assert_eq!(dt.day, 11); assert_eq!(dt.hour, Some(6)); assert_eq!(dt.minute, Some(41)); assert_eq!(dt.second, Some(8)); } }