use std::future::Future;
use std::time::{Duration, SystemTime};
tokio::task_local! {
static OFFSET: i64;
}
pub(crate) fn system_now() -> SystemTime {
let offset = OFFSET.try_with(|o| *o).unwrap_or(0);
let now = SystemTime::now();
if offset >= 0 {
now + Duration::from_secs(offset as u64)
} else {
now - Duration::from_secs(offset.unsigned_abs())
}
}
pub(crate) fn unix_secs() -> i64 {
system_now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_or(0, |d| d.as_secs() as i64)
}
pub(crate) fn unix_millis() -> i64 {
system_now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_or(0, |d| d.as_millis() as i64)
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct Stamp(i64);
impl Stamp {
pub(crate) fn now() -> Self {
Self(unix_millis())
}
pub(crate) fn elapsed(&self) -> Duration {
Duration::from_millis(u64::try_from(unix_millis() - self.0).unwrap_or(0))
}
}
pub(crate) fn with_offset_sync<T>(seconds: i64, f: impl FnOnce() -> T) -> T {
OFFSET.sync_scope(seconds, f)
}
pub(crate) async fn with_offset<F: Future>(seconds: i64, fut: F) -> F::Output {
OFFSET.scope(seconds, fut).await
}
pub(crate) fn carry<F: Future>(fut: F) -> impl Future<Output = F::Output> {
let offset = OFFSET.try_with(|o| *o).unwrap_or(0);
OFFSET.scope(offset, fut)
}