use std::time::{Duration, SystemTime};
pub struct Timer {
started: Option<SystemTime>,
laps: Vec<Duration>,
}
impl Timer {
pub fn new() -> Self {
Timer {
started: None,
laps: vec![],
}
}
pub fn start(&mut self) -> Result<(), &str> {
match self.started {
None => {
self.started = Some(SystemTime::now());
Ok(())
}
Some(_) => Err("Timer already started!")
}
}
pub fn start_time(&self) -> Result<SystemTime, &str> {
match self.started {
Some(s) => Ok(s.clone()),
None => Err("Timer not started!")
}
}
pub fn lap(&mut self) -> Result<Duration, String> {
match self.started {
Some(s) => {
match s.elapsed() {
Ok(e) => {
self.laps.push(e);
Ok(e.clone())
}
Err(e) =>
Err(format!("Internal Error: {:?}", e))
}
}
None => Err("Timer not started!".to_string())
}
}
pub fn laps(&self) -> Vec<Duration> {
self.laps.clone()
}
pub fn laps_formatted(&self) -> Vec<String> {
let formatted: Vec<String> = self.laps.iter().map(|d| duration_to_human_string(d)).collect();
formatted
}
}
pub fn duration_to_human_string(duration: &Duration) -> String {
return if duration.as_nanos() < 1000 {
format!("{}ns", duration.as_nanos())
} else if duration.as_micros() < 1000 {
format!("{}us", duration.as_micros())
} else if duration.as_millis() < 1000 {
format!("{}ms", duration.as_millis())
} else if duration.as_secs() < 60 {
format!("{}s", duration.as_secs())
}else {
format!("{}m", duration.as_secs() / 60)
}
}