1use chrono::{DateTime, Duration, Local};
15
16#[derive(Debug, Clone)]
17pub struct TimerData {
18 pub total: Duration,
19 pub remaining: Duration,
20 pub start_moments: Vec<DateTime<Local>>, pub pause_moments: Vec<DateTime<Local>>, }
23
24impl TimerData {
25 fn new(duration: Duration) -> Self {
26 Self {
27 total: duration,
28 remaining: duration,
29 start_moments: Vec::new(),
30 pause_moments: Vec::new(),
31 }
32 }
33 pub fn start(&self) -> DateTime<Local> {
34 self.start_moments[0]
35 }
36 pub fn stop(&self) -> DateTime<Local> {
37 self.pause_moments[self.pause_moments.len() - 1]
38 }
39 pub fn duration_expected(&self) -> Duration {
40 self.total
41 }
42 pub fn duration_actual(&self) -> Duration {
43 self.stop() - self.start()
44 }
45}
46
47#[derive(Clone, Debug)]
49pub struct Timer {
50 pub paused: bool,
51 pub data: TimerData,
52}
53
54impl Timer {
55 pub fn new(duration: Duration) -> Self {
57 Self {
58 paused: true, data: TimerData::new(duration),
60 }
61 }
62 pub fn read(&self) -> Duration {
64 if self.paused {
65 self.data.remaining
66 } else {
67 self.data.remaining - (Local::now() - self.last_start())
68 }
69 }
70 pub fn pause_or_resume(&mut self) {
72 self.pause_or_resume_at(Local::now());
73 }
74
75 pub fn pause_or_resume_at(&mut self, moment: DateTime<Local>) {
76 if self.paused {
77 self.resume_at(moment);
78 } else {
79 self.pause_at(moment);
80 }
81 }
82
83 pub fn pause(&mut self) {
85 self.pause_at(Local::now());
86 }
87
88 pub fn pause_at(&mut self, moment: DateTime<Local>) {
89 self.data.pause_moments.push(moment);
90 self.data.remaining = self.data.remaining - (moment - self.last_start());
91 self.paused = true;
92 }
93 pub fn resume(&mut self) {
95 self.resume_at(Local::now());
96 }
97
98 pub fn resume_at(&mut self, moment: DateTime<Local>) {
99 self.data.start_moments.push(moment);
100 self.paused = false;
101 }
102
103 pub fn stop(&mut self) -> TimerData {
105 self.stop_at(Local::now())
106 }
107
108 pub fn stop_at(&mut self, moment: DateTime<Local>) -> TimerData {
109 self.data.pause_moments.push(moment);
110 let duration = self.data.total;
111 let data = std::mem::replace(&mut self.data, TimerData::new(duration));
112 data
113 }
114
115 fn last_start(&self) -> DateTime<Local> {
116 self.data.start_moments[self.data.start_moments.len() - 1]
117 }
118}