use std::time::{SystemTime, UNIX_EPOCH};
pub fn format_timestamp_iso8601(timestamp: u64) -> String {
let Ok(timestamp) = i64::try_from(timestamp) else {
return format!("invalid-timestamp({timestamp})");
};
chrono::DateTime::from_timestamp(timestamp, 0)
.map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())
.unwrap_or_else(|| format!("invalid-timestamp({timestamp})"))
}
pub fn now_iso8601() -> String {
format_timestamp_iso8601(epoch_now())
}
pub fn epoch_now() -> u64 {
std::env::var("WORKTRUNK_TEST_EPOCH")
.ok()
.and_then(|val| val.parse::<u64>().ok())
.unwrap_or_else(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system clock before Unix epoch")
.as_secs()
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_epoch_now_returns_reasonable_timestamp() {
let now = epoch_now();
assert!(now > 1577836800, "epoch_now() should return current time");
}
#[test]
fn test_epoch_now_respects_test_epoch() {
if let Ok(epoch) = std::env::var("WORKTRUNK_TEST_EPOCH") {
let expected: u64 = epoch.parse().unwrap();
assert_eq!(epoch_now(), expected);
}
}
#[test]
fn test_format_timestamp_iso8601_u64_overflow() {
let too_large = (i64::MAX as u64) + 1;
let formatted = format_timestamp_iso8601(too_large);
assert!(formatted.starts_with("invalid-timestamp("));
}
#[test]
fn test_format_timestamp_iso8601_chrono_out_of_range() {
let chrono_out_of_range: u64 = 9_000_000_000_000; let formatted = format_timestamp_iso8601(chrono_out_of_range);
assert!(formatted.starts_with("invalid-timestamp("));
}
}