1use chrono::{DateTime, Duration, Local};
27use std::{default::Default, mem};
28
29#[derive(Debug)]
30pub struct StopwatchData {
32 pub elapsed: Duration,
33 pub pause_moments: Vec<DateTime<Local>>, pub start_moments: Vec<DateTime<Local>>, pub lap_moments: Vec<DateTime<Local>>, pub laps: Vec<Duration>, }
38
39impl Default for StopwatchData {
40 fn default() -> Self {
41 Self {
42 elapsed: Duration::zero(),
43 start_moments: Vec::new(),
44 pause_moments: Vec::new(),
45 lap_moments: Vec::new(),
46 laps: Vec::new(),
47 }
48 }
49}
50
51impl StopwatchData {
52 fn new() -> Self {
53 Self::default()
54 }
55 pub fn start(&self) -> DateTime<Local> {
56 self.start_moments[0]
57 }
58 pub fn stop(&self) -> DateTime<Local> {
59 self.pause_moments[self.pause_moments.len() - 1]
60 }
61}
62
63#[derive(Debug)]
64pub struct Stopwatch {
65 pub lap_elapsed: Duration, pub paused: bool,
67 pub data: StopwatchData,
68}
69
70impl Default for Stopwatch {
71 fn default() -> Self {
72 Self {
73 lap_elapsed: Duration::zero(),
74 paused: true, data: StopwatchData::new(),
76 }
77 }
78}
79
80impl Stopwatch {
81 pub fn new() -> Self {
85 Self::default()
86 }
87 pub fn read(&self) -> Duration {
89 if self.paused {
90 self.data.elapsed
91 } else {
92 self.data.elapsed + (Local::now() - self.last_start())
93 }
94 }
95 pub fn pause_or_resume(&mut self) {
97 self.pause_or_resume_at(Local::now());
98 }
99
100 pub fn pause_or_resume_at(&mut self, moment: DateTime<Local>) {
101 if self.paused {
102 self.resume_at(moment);
103 } else {
104 self.pause_at(moment);
105 }
106 }
107 pub fn lap(&mut self) -> Option<Duration> {
110 self.lap_at(Local::now())
111 }
112
113 pub fn lap_at(&mut self, moment: DateTime<Local>) -> Option<Duration> {
114 if self.paused {
116 None
117 } else {
118 let lap = self.read_lap_elapsed(moment);
119 self.data.lap_moments.push(moment);
120 self.data.laps.push(lap);
121 self.lap_elapsed = Duration::zero();
122 Some(lap)
123 }
124 }
125
126 pub fn stop(&mut self) -> StopwatchData {
128 self.stop_at(Local::now())
129 }
130
131 pub fn stop_at(&mut self, moment: DateTime<Local>) -> StopwatchData {
132 let lap = self.read_lap_elapsed(moment);
134 self.data.lap_moments.push(moment);
135 self.data.laps.push(lap);
136 self.lap_elapsed = Duration::zero();
137 self.data.pause_moments.push(moment);
139 self.data.elapsed = self.data.elapsed + (moment - self.last_start());
140 self.paused = true;
141 let data = mem::replace(&mut self.data, StopwatchData::new());
143 data
144 }
145
146 fn read_lap_elapsed(&self, moment: DateTime<Local>) -> Duration {
148 self.lap_elapsed
149 + if self.lap_elapsed == Duration::zero() && !self.data.lap_moments.is_empty() {
150 moment - self.last_lap()
151 } else {
152 moment - self.last_start()
153 }
154 }
155
156 fn last_start(&self) -> DateTime<Local> {
157 self.data.start_moments[self.data.start_moments.len() - 1]
158 }
159 fn last_lap(&self) -> DateTime<Local> {
160 self.data.lap_moments[self.data.lap_moments.len() - 1]
161 }
162 pub fn pause(&mut self) {
164 self.pause_at(Local::now());
165 }
166 pub fn resume(&mut self) {
168 self.resume_at(Local::now());
169 }
170
171 pub fn pause_at(&mut self, moment: DateTime<Local>) {
172 self.data.pause_moments.push(moment);
173 self.data.elapsed = self.data.elapsed + (moment - self.last_start());
174 self.lap_elapsed = self.read_lap_elapsed(moment);
175 self.paused = true;
176 }
177
178 pub fn resume_at(&mut self, moment: DateTime<Local>) {
179 self.data.start_moments.push(moment);
180 self.paused = false;
181 }
182}