use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg_attr(test, mutants::skip)]
#[must_use]
pub(crate) fn unix_now_ms() -> u64 {
unix_ms_at(SystemTime::now())
}
#[must_use]
fn unix_ms_at(time: SystemTime) -> u64 {
time.duration_since(UNIX_EPOCH).map_or(0, since_epoch_ms)
}
#[must_use]
fn since_epoch_ms(elapsed: Duration) -> u64 {
u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX)
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use super::*;
#[test]
fn whole_milliseconds_are_what_survive_the_conversion() {
assert_eq!(since_epoch_ms(Duration::ZERO), 0);
assert_eq!(since_epoch_ms(Duration::from_millis(1_500)), 1_500);
assert_eq!(since_epoch_ms(Duration::from_micros(1_999)), 1);
}
#[test]
fn a_post_epoch_system_time_reaches_the_millisecond_conversion() {
let time = UNIX_EPOCH
.checked_add(Duration::from_micros(1_500_999))
.unwrap();
assert_eq!(unix_ms_at(time), 1_500);
assert_eq!(unix_ms_at(UNIX_EPOCH), 0);
}
#[test]
fn a_duration_too_large_to_express_saturates() {
assert_eq!(since_epoch_ms(Duration::MAX), u64::MAX);
}
#[test]
fn a_clock_set_before_the_epoch_reads_as_the_epoch() {
let before = UNIX_EPOCH.checked_sub(Duration::from_secs(1)).unwrap();
assert_eq!(unix_ms_at(before), 0);
}
}