40 lines
1.0 KiB
Rust
40 lines
1.0 KiB
Rust
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);
|
|
}
|
|
}
|