chrono_timesource/
lib.rs

1use chrono::prelude::*;
2use std::fmt::Debug;
3
4#[derive(Debug, Copy, Clone, Eq, PartialEq)]
5pub enum TimeSourceError {
6    DateTimeNotSet,
7}
8
9pub trait TimeSource<Tz: TimeZone>: Debug + Send + Sync + Clone {
10    fn now(&self) -> Result<DateTime<Tz>, TimeSourceError>;
11}
12
13#[derive(Debug, Copy, Clone)]
14pub struct UtcTimeSource;
15
16impl TimeSource<Utc> for UtcTimeSource {
17    fn now(&self) -> Result<DateTime<Utc>, TimeSourceError> {
18        Ok(Utc::now())
19    }
20}
21
22#[derive(Debug, Clone)]
23pub struct ManualTimeSource<Tz: TimeZone> {
24    instant: Option<DateTime<Tz>>,
25}
26
27impl<Tz: TimeZone> ManualTimeSource<Tz> {
28    pub fn new() -> Self {
29        ManualTimeSource { instant: None }
30    }
31    pub fn set_now(&mut self, now: DateTime<Tz>) {
32        self.instant = Some(now);
33    }
34}
35
36impl<Tz: TimeZone + Debug> TimeSource<Tz> for ManualTimeSource<Tz>
37where
38    <Tz as TimeZone>::Offset: Sync + Send + Clone + Debug,
39{
40    fn now(&self) -> Result<DateTime<Tz>, TimeSourceError> {
41        self.instant.clone().ok_or(TimeSourceError::DateTimeNotSet)
42    }
43}
44
45#[cfg(test)]
46mod test {
47    use super::*;
48
49    #[test]
50    fn manual_now() {
51        let mut manual_time_source: ManualTimeSource<Utc> = ManualTimeSource::new();
52        manual_time_source.set_now(Utc.with_ymd_and_hms(1970, 1, 1, 0, 1, 1).unwrap());
53        assert_eq!(
54            manual_time_source.now(),
55            Ok(Utc.with_ymd_and_hms(1970, 1, 1, 0, 1, 1).unwrap())
56        );
57    }
58
59    #[test]
60    fn manual_uninitialised() {
61        let manual_time_source: ManualTimeSource<Utc> = ManualTimeSource::new();
62        assert_eq!(
63            manual_time_source.now(),
64            Err(TimeSourceError::DateTimeNotSet)
65        );
66    }
67}