const DAYS_TO_MARCH_ZERO: u64 = 719_468;
const SECONDS_PER_DAY: u64 = 86_400;
pub fn rfc3339(seconds: u64) -> String {
let days = seconds / SECONDS_PER_DAY;
let time_of_day = seconds % SECONDS_PER_DAY;
let (year, month, day) = civil_from_days(days);
let (hour, minute, second) = (
time_of_day / 3_600,
(time_of_day % 3_600) / 60,
time_of_day % 60,
);
format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}Z")
}
fn civil_from_days(days: u64) -> (u64, u64, u64) {
let shifted = days + DAYS_TO_MARCH_ZERO;
let era = shifted / 146_097;
let day_of_era = shifted % 146_097;
let year_of_era =
(day_of_era - day_of_era / 1_460 + day_of_era / 36_524 - day_of_era / 146_096) / 365;
let day_of_year = day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100);
let month_index = (5 * day_of_year + 2) / 153;
let day = day_of_year - (153 * month_index + 2) / 5 + 1;
let month = if month_index < 10 {
month_index + 3
} else {
month_index - 9
};
let year = year_of_era + era * 400 + u64::from(month <= 2);
(year, month, day)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_epoch_is_the_epoch() {
assert_eq!(rfc3339(0), "1970-01-01T00:00:00Z");
}
#[test]
fn a_time_of_day_is_carried_whole() {
assert_eq!(rfc3339(1_000_000_000), "2001-09-09T01:46:40Z");
assert_eq!(rfc3339(86_399), "1970-01-01T23:59:59Z");
assert_eq!(rfc3339(86_400), "1970-01-02T00:00:00Z");
}
#[test]
fn a_leap_day_is_a_day() {
assert_eq!(rfc3339(1_709_164_800), "2024-02-29T00:00:00Z");
assert_eq!(rfc3339(951_782_400), "2000-02-29T00:00:00Z");
assert_eq!(rfc3339(1_709_251_199), "2024-02-29T23:59:59Z");
assert_eq!(rfc3339(1_709_251_200), "2024-03-01T00:00:00Z");
}
#[test]
fn the_year_2038_is_an_ordinary_tuesday() {
assert_eq!(rfc3339(2_147_483_647), "2038-01-19T03:14:07Z");
}
#[test]
fn a_rendered_second_sorts_the_way_the_second_did() {
let mut rendered = [1_709_164_800_u64, 0, 2_147_483_647, 1_000_000_000]
.map(rfc3339)
.to_vec();
rendered.sort();
assert_eq!(
rendered,
vec![
"1970-01-01T00:00:00Z",
"2001-09-09T01:46:40Z",
"2024-02-29T00:00:00Z",
"2038-01-19T03:14:07Z",
]
);
}
}