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
use std::time::{Instant, Duration}; use std::borrow::Borrow; pub struct DoEvery { started: Instant, last_check: Option<Instant>, } impl DoEvery { pub fn new() -> Self { DoEvery { started: Instant::now(), last_check: None } } pub fn should_do_every(&mut self, period: impl Borrow<Duration>) -> bool { self.should_do_every_sec(period.borrow().as_secs_f32()) } pub fn should_do_every_sec(&mut self, sec: impl Into<f32>) -> bool { let sec: f32 = sec.into(); let now = Instant::now(); let time_since_start = (now - self.started).as_secs_f32(); let period_currently_in: u64 = (time_since_start / sec).trunc() as u64; let previous_check_time = self.last_check; self.last_check = Some(now); if period_currently_in == 0 { false } else { match previous_check_time { None => true, Some(previous_check_time) => { let previous_period = ((previous_check_time - self.started).as_secs_f32() / sec).trunc() as u64; previous_period != period_currently_in }, } } } pub fn should_do_every_min(&mut self, mins: impl Into<f32>) -> bool { self.should_do_every_sec(mins.into() * 60.) } } #[cfg(test)] mod tests { use super::*; use std::thread::sleep; #[test] fn test1() { let mut counter = DoEvery::new(); sleep(Duration::from_millis(50)); assert!(counter.should_do_every_sec(0.01)); } #[test] fn test2() { let mut counter = DoEvery::new(); sleep(Duration::from_millis(50)); assert!(!counter.should_do_every_sec(0.5)); } #[test] fn test3() { let mut counter = DoEvery::new(); sleep(Duration::from_millis(10)); assert!(!counter.should_do_every(Duration::from_millis(25))); sleep(Duration::from_millis(10)); assert!(!counter.should_do_every(Duration::from_millis(25))); sleep(Duration::from_millis(10)); assert!(counter.should_do_every(Duration::from_millis(25))); } }