use std::{
sync::atomic::{AtomicI64, Ordering},
time::Duration,
};
use instant::SystemTime;
#[derive(Debug, Default)]
pub struct OffsetTime {
offset: AtomicI64,
}
impl OffsetTime {
pub fn new() -> Self {
OffsetTime::with_offset(0)
}
pub fn with_offset(offset: i64) -> Self {
OffsetTime {
offset: AtomicI64::new(offset),
}
}
pub fn set_offset(&self, new_offset: i64) {
self.offset.store(new_offset, Ordering::Relaxed);
}
pub fn now(&self) -> u64 {
let offset = self.offset.load(Ordering::Relaxed);
let abs_offset = offset.unsigned_abs();
let system_time = if offset > 0 {
SystemTime::now() + Duration::from_millis(abs_offset)
} else {
SystemTime::now() - Duration::from_millis(abs_offset)
};
systemtime_to_timestamp(system_time)
}
}
pub fn systemtime_to_timestamp(time: SystemTime) -> u64 {
match time.duration_since(SystemTime::UNIX_EPOCH) {
Ok(duration) => duration.as_secs() * 1000 + u64::from(duration.subsec_nanos()) / 1_000_000,
Err(_) => panic!("SystemTime before UNIX EPOCH"),
}
}
pub fn timestamp_to_systemtime(timestamp: u64) -> SystemTime {
SystemTime::UNIX_EPOCH + Duration::from_millis(timestamp)
}