OXYGENHUB

Coverage / crates/hub/src/render/time.rs 92.7%

51 of 55 lines run, 12 of 12 functions · run #474 on main · run missed

1
//! Times as people read them: relative ("3 hours ago") with the absolute
2
//! form for a tooltip.
3
4
use time::format_description::well_known::Rfc3339;
5
use time::OffsetDateTime;
6
7
/// `just now`, `5 minutes ago`, `3 days ago`, `2 years ago`.
81503×
pub fn ago(when_ms: u64, now_ms: u64) -> String {
91503×
    if when_ms == 0 {
1024×
        return "unknown".into();
111479×
    }
121479×
    if when_ms > now_ms {
133×
        return "in the future".into();
141476×
    }
151476×
    let s = (now_ms - when_ms) / 1000;
161476×
    let (n, unit) = if s < 45 {
171446×
        return "just now".into();
1830×
    } else if s < 90 {
191×
        (1, "minute")
2029×
    } else if s < 3600 {
211×
        (s / 60, "minute")
2228×
    } else if s < 86_400 {
231×
        (s / 3600, "hour")
2427×
    } else if s < 86_400 * 30 {
257×
        (s / 86_400, "day")
2620×
    } else if s < 86_400 * 365 {
271×
        (s / (86_400 * 30), "month")
28
    } else {
2919×
        (s / (86_400 * 365), "year")
30
    };
3130×
    format!("{n} {unit}{} ago", if n == 1 { "" } else { "s" })
321503×
}
33
34
/// `2026-09-27 17:02 UTC`.
351478×
pub fn absolute(when_ms: u64) -> String {
361478×
    match OffsetDateTime::from_unix_timestamp((when_ms / 1000) as i64) {
371478×
        Ok(t) => {
381478×
            let f = time::macros::format_description!("[year]-[month]-[day] [hour]:[minute] UTC");
391478×
            t.format(&f).unwrap_or_default()
40
        }
410×
        Err(_) => String::new(),
42
    }
431478×
}
44
45
/// `21 Oct 2026`, the UTC day.
463×
pub fn day(when_ms: u64) -> String {
473×
    match OffsetDateTime::from_unix_timestamp((when_ms / 1000) as i64) {
483×
        Ok(t) => {
493×
            let f = time::macros::format_description!("[day padding:none] [month repr:short] [year]");
503×
            t.format(&f).unwrap_or_default()
51
        }
520×
        Err(_) => String::new(),
53
    }
543×
}
55
568×
pub fn rfc3339(when_ms: u64) -> String {
578×
    OffsetDateTime::from_unix_timestamp((when_ms / 1000) as i64).ok().and_then(|t| t.format(&Rfc3339).ok()).unwrap_or_default()
588×
}
59
60
#[cfg(test)]
61
mod tests {
62
    use super::*;
63
64
    #[test]
651×
    fn days() {
661×
        assert_eq!(day(1_792_540_800_000), "21 Oct 2026");
671×
    }
68
69
    #[test]
701×
    fn relative() {
711×
        let now = 1_800_000_000_000;
721×
        assert_eq!(ago(now - 10_000, now), "just now");
731×
        assert_eq!(ago(now - 60_000, now), "1 minute ago");
741×
        assert_eq!(ago(now - 5 * 60_000, now), "5 minutes ago");
751×
        assert_eq!(ago(now - 3 * 3_600_000, now), "3 hours ago");
761×
        assert_eq!(ago(now - 2 * 86_400_000, now), "2 days ago");
771×
        assert_eq!(ago(now - 400 * 86_400_000, now), "1 year ago");
781×
        assert_eq!(ago(0, now), "unknown");
791×
        assert_eq!(absolute(1_758_990_120_000), "2025-09-27 16:22 UTC");
801×
    }
81
}