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}