1use std::sync::Arc;
4use std::time::{SystemTime, UNIX_EPOCH};
5
6pub trait TimestampSource: Send + Sync {
8 fn now_timestamp_seconds(&self) -> i64;
10}
11
12impl<TimestampFn> TimestampSource for TimestampFn
13where
14 TimestampFn: Fn() -> i64 + Send + Sync,
15{
16 fn now_timestamp_seconds(&self) -> i64 {
17 self()
18 }
19}
20
21pub(crate) fn system_timestamp_source() -> Arc<dyn TimestampSource> {
23 Arc::new(system_timestamp_seconds)
24}
25
26fn system_timestamp_seconds() -> i64 {
28 SystemTime::now()
29 .duration_since(UNIX_EPOCH)
30 .ok()
31 .and_then(|duration| i64::try_from(duration.as_secs()).ok())
32 .unwrap_or_default()
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn closure_timestamp_source_returns_injected_value() {
41 let timestamp_source = || 123;
43
44 let timestamp = timestamp_source.now_timestamp_seconds();
46
47 assert_eq!(timestamp, 123);
49 }
50
51 #[test]
52 fn system_timestamp_source_returns_a_post_epoch_value() {
53 let timestamp_source = system_timestamp_source();
55
56 let timestamp = timestamp_source.now_timestamp_seconds();
58
59 assert!(timestamp > 0);
61 }
62}