use std::{ time::{ Duration, Instant, SystemTime, } }; pub fn get_next_tick (interval_secs: u64, offset_secs: u64) -> Instant { let now_sys = SystemTime::now (); let now_mono = Instant::now (); let phase = get_phase (now_sys, interval_secs, offset_secs); now_mono.checked_add (Duration::from_millis (interval_secs * 1000 - u64::try_from (phase).unwrap ())).unwrap () } fn get_phase (now: SystemTime, interval_secs: u64, offset_secs: u64) -> u64 { let ms_since_epoch = now.duration_since (SystemTime::UNIX_EPOCH).unwrap ().as_millis (); u64::try_from ((ms_since_epoch + u128::from (offset_secs) * 1000) % (u128::from (interval_secs) * 1000)).unwrap () } #[cfg (test)] mod test { use super::*; #[test] fn test () { let now = SystemTime::UNIX_EPOCH.checked_add (Duration::from_secs (1649201544)).unwrap (); assert_eq! (get_phase (now, 2225, 0), 394000); assert_eq! (get_phase (now, 2225, 30), 424000); } }