use chrono::{DateTime, Utc};
pub fn resolve_now() -> DateTime<Utc> {
std::env::var("SOURCE_DATE_EPOCH")
.ok()
.and_then(|s| s.parse::<i64>().ok())
.and_then(|secs| DateTime::<Utc>::from_timestamp(secs, 0))
.unwrap_or_else(Utc::now)
}
pub fn source_date_epoch() -> Option<DateTime<Utc>> {
std::env::var("SOURCE_DATE_EPOCH")
.ok()
.and_then(|s| s.parse::<i64>().ok())
.and_then(|secs| DateTime::<Utc>::from_timestamp(secs, 0))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[serial_test::serial(env)]
fn resolve_now_honors_source_date_epoch() {
unsafe { std::env::set_var("SOURCE_DATE_EPOCH", "1715000000") };
let now = resolve_now();
assert_eq!(now.timestamp(), 1715000000);
unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
}
#[test]
#[serial_test::serial(env)]
fn resolve_now_ignores_malformed_sde() {
unsafe { std::env::set_var("SOURCE_DATE_EPOCH", "not-a-number") };
let now = resolve_now();
assert!(now.timestamp() > 1_577_836_800); unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
}
#[test]
#[serial_test::serial(env)]
fn resolve_now_falls_back_when_unset() {
unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
let now = resolve_now();
assert!(now.timestamp() > 1_577_836_800);
}
#[test]
#[serial_test::serial(env)]
fn source_date_epoch_returns_some_when_set() {
unsafe { std::env::set_var("SOURCE_DATE_EPOCH", "1715000000") };
let dt = source_date_epoch();
assert_eq!(dt.map(|d| d.timestamp()), Some(1715000000));
unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
}
#[test]
#[serial_test::serial(env)]
fn source_date_epoch_returns_none_when_unset() {
unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
assert!(source_date_epoch().is_none());
}
#[test]
#[serial_test::serial(env)]
fn source_date_epoch_returns_none_when_malformed() {
unsafe { std::env::set_var("SOURCE_DATE_EPOCH", "not-a-number") };
assert!(source_date_epoch().is_none());
unsafe { std::env::remove_var("SOURCE_DATE_EPOCH") };
}
}