use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::{Context, Result};
pub fn toasty_prefix_now() -> Result<String> {
let stamp = format_utc(now_secs()?);
Ok(format!("{}_{}", &stamp[..8], &stamp[8..]))
}
fn now_secs() -> Result<u64> {
Ok(SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("system clock is set before 1970")?
.as_secs())
}
fn format_utc(unix_secs: u64) -> String {
let (days, rem) = (unix_secs / 86_400, unix_secs % 86_400);
let (year, month, day) = civil_from_days(days);
format!(
"{year:04}{month:02}{day:02}{:02}{:02}{:02}",
rem / 3600,
rem % 3600 / 60,
rem % 60
)
}
fn civil_from_days(days: u64) -> (u64, u64, u64) {
let z = days + 719_468;
let era = z / 146_097;
let doe = z % 146_097;
let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let day = doy - (153 * mp + 2) / 5 + 1;
let month = if mp < 10 { mp + 3 } else { mp - 9 };
let year = yoe + era * 400 + u64::from(month <= 2);
(year, month, day)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn formats_known_instants() {
assert_eq!(format_utc(0), "19700101000000");
assert_eq!(format_utc(951_782_400), "20000229000000"); assert_eq!(format_utc(1_700_000_000), "20231114221320");
assert_eq!(format_utc(1_791_741_599), "20261011175959");
}
#[test]
fn toasty_prefix_has_date_and_time() {
let prefix = toasty_prefix_now().unwrap();
assert_eq!(prefix.len(), 15);
assert_eq!(&prefix[8..9], "_");
assert!(prefix.as_str() > "2026");
}
}