pub use crate::time::UNIX_EPOCH_TICKS;
#[cfg(feature = "time")]
use crate::time::now_ticks;
pub const TICKS_PER_SECOND: i64 = 10_000_000;
pub const TICKS_PER_MILLISECOND: i64 = 10_000;
#[cfg(feature = "time")]
#[inline]
pub fn utc_now_ticks() -> i64 {
now_ticks()
}
#[cfg(feature = "time")]
#[inline]
pub fn seconds_from_diff_utc_now_ticks(ticks: i64) -> i64 {
seconds_from_diff_ticks(ticks, utc_now_ticks())
}
#[inline]
pub fn seconds_from_diff_ticks(ticks: i64, now_ticks: i64) -> i64 {
if ticks > 0 {
let diff = ticks - now_ticks;
if diff > 0 {
(diff + TICKS_PER_SECOND / 2) / TICKS_PER_SECOND
} else {
-1
}
} else {
-1
}
}
#[cfg(feature = "time")]
#[inline]
pub fn milliseconds_from_diff_utc_now_ticks(ticks: i64) -> i64 {
milliseconds_from_diff_ticks(ticks, utc_now_ticks())
}
#[inline]
pub fn milliseconds_from_diff_ticks(ticks: i64, now_ticks: i64) -> i64 {
if ticks > 0 {
let diff = ticks - now_ticks;
if diff > 0 {
diff / TICKS_PER_MILLISECOND
} else {
-1
}
} else {
-1
}
}
#[inline]
pub fn unix_timestamp_in_seconds_to_ticks(unix_timestamp: i64) -> i64 {
unix_timestamp * TICKS_PER_SECOND + UNIX_EPOCH_TICKS
}
#[inline]
pub fn unix_timestamp_in_milliseconds_to_ticks(unix_timestamp: i64) -> i64 {
unix_timestamp * TICKS_PER_MILLISECOND + UNIX_EPOCH_TICKS
}
#[inline]
pub fn unix_time_in_seconds_from_ticks(ticks: i64) -> i64 {
if ticks > 0 {
(ticks - UNIX_EPOCH_TICKS) / TICKS_PER_SECOND
} else {
-1
}
}
#[inline]
pub fn unix_time_in_milliseconds_from_ticks(ticks: i64) -> i64 {
if ticks > 0 {
(ticks - UNIX_EPOCH_TICKS) / TICKS_PER_MILLISECOND
} else {
-1
}
}
pub const MAX_UNIX_TIMESTAMP_SECONDS: i64 = (i64::MAX - UNIX_EPOCH_TICKS) / TICKS_PER_SECOND;
pub const MAX_UNIX_TIMESTAMP_MILLISECONDS: i64 =
(i64::MAX - UNIX_EPOCH_TICKS) / TICKS_PER_MILLISECOND;
#[inline]
pub fn duration_seconds_to_ticks(seconds: i64) -> i64 {
seconds.saturating_mul(TICKS_PER_SECOND)
}
#[inline]
pub fn duration_milliseconds_to_ticks(milliseconds: i64) -> i64 {
milliseconds.saturating_mul(TICKS_PER_MILLISECOND)
}
#[inline]
pub fn expire_after_to_ticks(now_ticks: i64, seconds: i64) -> i64 {
now_ticks.saturating_add(duration_seconds_to_ticks(seconds))
}
#[inline]
pub fn expire_after_ms_to_ticks(now_ticks: i64, milliseconds: i64) -> i64 {
now_ticks.saturating_add(duration_milliseconds_to_ticks(milliseconds))
}
#[inline]
pub fn expire_at_seconds_to_ticks(unix_seconds: i64) -> i64 {
unix_timestamp_in_seconds_to_ticks(unix_seconds.clamp(0, MAX_UNIX_TIMESTAMP_SECONDS))
}
#[inline]
pub fn expire_at_milliseconds_to_ticks(unix_milliseconds: i64) -> i64 {
unix_timestamp_in_milliseconds_to_ticks(
unix_milliseconds.clamp(0, MAX_UNIX_TIMESTAMP_MILLISECONDS),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn duration_saturates() {
assert_eq!(duration_seconds_to_ticks(i64::MAX), i64::MAX);
assert_eq!(duration_seconds_to_ticks(i64::MIN), i64::MIN);
assert_eq!(duration_milliseconds_to_ticks(i64::MAX), i64::MAX);
assert_eq!(duration_milliseconds_to_ticks(i64::MIN), i64::MIN);
assert_eq!(duration_seconds_to_ticks(1), TICKS_PER_SECOND);
assert_eq!(duration_milliseconds_to_ticks(1), TICKS_PER_MILLISECOND);
}
#[test]
fn expire_after_saturates() {
let now = 70_000_000_000_000_000;
assert_eq!(expire_after_to_ticks(now, 10), now + 10 * TICKS_PER_SECOND);
assert_eq!(
expire_after_ms_to_ticks(now, 10),
now + 10 * TICKS_PER_MILLISECOND
);
assert_eq!(expire_after_to_ticks(now, i64::MAX), i64::MAX);
assert_eq!(expire_after_ms_to_ticks(now, i64::MAX), i64::MAX);
for seconds in [0, 1, 60, 3_600, 86_400] {
assert_eq!(
expire_after_to_ticks(now, seconds) - now,
duration_seconds_to_ticks(seconds)
);
assert_eq!(
expire_after_ms_to_ticks(now, seconds) - now,
duration_milliseconds_to_ticks(seconds)
);
}
}
#[test]
fn expire_at_clamps() {
assert_eq!(expire_at_seconds_to_ticks(-5), UNIX_EPOCH_TICKS);
assert_eq!(expire_at_seconds_to_ticks(0), UNIX_EPOCH_TICKS);
assert_eq!(
expire_at_seconds_to_ticks(100),
unix_timestamp_in_seconds_to_ticks(100)
);
assert_eq!(
expire_at_seconds_to_ticks(MAX_UNIX_TIMESTAMP_SECONDS),
i64::MAX - (i64::MAX - UNIX_EPOCH_TICKS) % TICKS_PER_SECOND
);
assert_eq!(
expire_at_seconds_to_ticks(i64::MAX),
i64::MAX - (i64::MAX - UNIX_EPOCH_TICKS) % TICKS_PER_SECOND
);
assert_eq!(expire_at_milliseconds_to_ticks(-1), UNIX_EPOCH_TICKS);
assert_eq!(
expire_at_milliseconds_to_ticks(MAX_UNIX_TIMESTAMP_MILLISECONDS),
i64::MAX - (i64::MAX - UNIX_EPOCH_TICKS) % TICKS_PER_MILLISECOND
);
assert_eq!(
expire_at_milliseconds_to_ticks(i64::MAX),
i64::MAX - (i64::MAX - UNIX_EPOCH_TICKS) % TICKS_PER_MILLISECOND
);
}
#[test]
fn cap_constants_match_clamp() {
assert_eq!(
MAX_UNIX_TIMESTAMP_SECONDS,
(i64::MAX - UNIX_EPOCH_TICKS) / TICKS_PER_SECOND
);
assert_eq!(
MAX_UNIX_TIMESTAMP_MILLISECONDS,
(i64::MAX - UNIX_EPOCH_TICKS) / TICKS_PER_MILLISECOND
);
for over in [MAX_UNIX_TIMESTAMP_SECONDS + 1, i64::MAX] {
assert_eq!(
expire_at_seconds_to_ticks(over),
expire_at_seconds_to_ticks(MAX_UNIX_TIMESTAMP_SECONDS)
);
}
for over in [MAX_UNIX_TIMESTAMP_MILLISECONDS + 1, i64::MAX] {
assert_eq!(
expire_at_milliseconds_to_ticks(over),
expire_at_milliseconds_to_ticks(MAX_UNIX_TIMESTAMP_MILLISECONDS)
);
}
}
}