use std::time::{Duration, SystemTime, UNIX_EPOCH}; #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] pub struct Timestamp(pub SystemTime); impl Timestamp { pub const ZERO: Timestamp = Timestamp(UNIX_EPOCH); pub fn now() -> Timestamp { return Timestamp(SystemTime::now()); } pub fn duration_since(self, earlier: Timestamp) -> Result { return self.0.duration_since(earlier.0); } } impl std::ops::Add for Timestamp { type Output = Timestamp; fn add(self, rhs: Duration) -> Timestamp { return Timestamp(self.0 + rhs); } } impl std::ops::Sub for Timestamp { type Output = Timestamp; fn sub(self, rhs: Duration) -> Timestamp { return Timestamp(self.0 - rhs); } } fn is_leap_year(y: u64) -> bool { return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); } fn days_in_month(y: u64, m: u64) -> u64 { match m { 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 4 | 6 | 9 | 11 => 30, 2 => if is_leap_year(y) { 29 } else { 28 }, _ => panic!("invalid month"), } } pub fn secs_to_ymd_hms(mut secs: u64) -> (u64, u64, u64, u64, u64, u64) { let s = secs % 60; secs /= 60; let min = secs % 60; secs /= 60; let h = secs % 24; let mut days = secs / 24; let mut y = 1970u64; loop { let days_in_year = if is_leap_year(y) { 366 } else { 365 }; if days < days_in_year { break; } days -= days_in_year; y += 1; } let mut mo = 1u64; loop { let dim = days_in_month(y, mo); if days < dim { break; } days -= dim; mo += 1; } let day = days + 1; return (y, mo, day, h, min, s); } pub fn ymd_hms_to_secs(y: u64, m: u64, d: u64, h: u64, min: u64, s: u64) -> u64 { let mut days = 0u64; for year in 1970..y { days += if is_leap_year(year) { 366 } else { 365 }; } for month in 1..m { days += days_in_month(y, month); } days += d - 1; return days * 86400 + h * 3600 + min * 60 + s; }