web_instant 0.3.0

Cross platform impl of Instant
Documentation
use std::fmt::{Debug, Formatter};
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::{Duration, Instant, SystemTime};

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Spot {
	inner: Instant,
}

impl Debug for Spot {
	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
		self.inner.fmt(f)
	}
}

impl Spot {
	pub fn now() -> Self {
		Spot {
			inner: Instant::now(),
		}
	}
	/// Returns the amount of time elapsed since this instant was created.
	pub fn elapsed(&self) -> Duration {
		Spot::now() - *self
	}
	/// Returns the amount of time elapsed from another instant to this one,
	/// or zero duration if that instant is later than this one.
	pub fn duration_since(&self, earlier: Spot) -> Duration {
		self.checked_duration_since(earlier).unwrap_or_default()
	}
	/// Returns the amount of time elapsed from another instant to this one,
	/// or None if that instant is later than this one.
	///
	/// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s,
	/// this method can return `None`.
	pub fn checked_duration_since(&self, earlier: Spot) -> Option<Duration> {
		self.inner.checked_duration_since(earlier.inner)
	}
	/// Returns the amount of time elapsed from another instant to this one,
	/// or zero duration if that instant is later than this one.
	pub fn saturating_duration_since(&self, earlier: Spot) -> Duration {
		self.inner.saturating_duration_since(earlier.inner)
	}
	/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
	/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
	/// otherwise.
	pub fn checked_add(&self, duration: Duration) -> Option<Spot> {
		self.inner.checked_add(duration).map(|inner| Spot { inner })
	}
	/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
	/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
	/// otherwise.
	pub fn checked_sub(&self, duration: Duration) -> Option<Spot> {
		self.inner.checked_sub(duration).map(|inner| Spot { inner })
	}

	/// Converts this `Spot` into a duration that represents the time that has elapsed between the
	/// UNIX Epoch and this `Spot`
	pub fn duration_since_epoch(&self) -> Duration {
		let duration_since_epoch = SystemTime::now()
			.duration_since(SystemTime::UNIX_EPOCH)
			.expect("Failed to get time since epoch");

		let duration_since_instant = self.elapsed();

		duration_since_epoch - duration_since_instant
	}
}

impl Add<Duration> for Spot {
	type Output = Spot;

	/// # Panics
	///
	/// This function may panic if the resulting point in time cannot be represented by the
	/// underlying data structure. See [`Spot::checked_add`] for a version without panic.
	fn add(self, other: Duration) -> Spot {
		self.checked_add(other)
			.expect("overflow when adding duration to instant")
	}
}

impl AddAssign<Duration> for Spot {
	fn add_assign(&mut self, other: Duration) {
		*self = *self + other;
	}
}

impl Sub<Duration> for Spot {
	type Output = Spot;

	fn sub(self, other: Duration) -> Spot {
		self.checked_sub(other)
			.expect("overflow when subtracting duration from instant")
	}
}

impl SubAssign<Duration> for Spot {
	fn sub_assign(&mut self, other: Duration) {
		*self = *self - other;
	}
}

impl Sub<Spot> for Spot {
	type Output = Duration;

	/// Returns the amount of time elapsed from another instant to this one,
	/// or zero duration if that instant is later than this one.
	fn sub(self, other: Spot) -> Duration {
		self.duration_since(other)
	}
}