1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
extern crate chrono;
use std::time::{SystemTime, UNIX_EPOCH};
use chrono::{NaiveDate, Utc, DateTime};
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Time {
pub epoch: u64,
pub elapsed: u64,
pub till: u64,
}
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Config {
pub epoch: u64,
pub period: u64,
}
#[derive(PartialEq, Debug, Clone, Default)]
pub struct Clock {
cfg: Config,
}
impl Clock {
pub fn new(cfg: Config) -> Self {
Clock {
cfg: cfg,
}
}
pub fn period(&self) -> u64 {
self.cfg.period
}
pub fn new_katzenpost() -> Self {
Clock {
cfg: Config {
epoch: (DateTime::<Utc>::from_utc(NaiveDate::from_ymd(2017, 6, 1).and_hms(0,0,0), Utc) -
DateTime::<Utc>::from_utc(NaiveDate::from_ymd(1970, 1, 1).and_hms(0,0,0), Utc))
.num_seconds() as u64,
period: 3 * 60 * 60,
},
}
}
pub fn now(&self) -> Time {
self.get_epoch(SystemTime::now())
}
pub fn is_in_epoch(&self, e: u64, t: u64) -> bool {
let delta_start = e * self.cfg.period;
let delta_end = (e+1) * self.cfg.period;
let start_time = self.cfg.epoch.wrapping_add(delta_start);
let end_time = self.cfg.epoch.wrapping_add(delta_end);
if t == start_time {
return true
}
if t > start_time && t < end_time {
return true
}
return false
}
fn get_epoch(&self, _time: SystemTime) -> Time {
let now = match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(x) => x.as_secs(),
Err(e) => panic!(e),
};
let from_epoch = now.wrapping_sub(self.cfg.epoch);
let current: u64 = from_epoch / self.cfg.period;
let base = self.cfg.epoch.wrapping_add(current * self.cfg.period);
let unix_time = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => n.as_secs() as u64,
Err(_) => panic!("SystemTime is before the Unix epoch"),
};
let elapsed = unix_time.wrapping_sub(base);
let till = (base + self.cfg.period).wrapping_sub(unix_time);
Time{
epoch: current,
elapsed: elapsed,
till: till,
}
}
}
#[cfg(test)]
mod tests {
use std::time::{SystemTime, UNIX_EPOCH};
use super::Clock;
#[test]
fn basic_time_now_test() {
let e = Clock::new_katzenpost();
let now = e.now();
println!("current {} elapsed {} till {}", now.epoch, now.elapsed, now.till);
}
#[test]
fn is_in_epoch_test() {
let e = Clock::new_katzenpost();
let now = e.now();
let unix_epoch_now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let now_secs = unix_epoch_now.as_secs();
assert_eq!(e.is_in_epoch(now.epoch, now_secs), true);
}
}