From bb1201c3ea19a126938b4a3dadcb906873993a1b Mon Sep 17 00:00:00 2001
From: Louis Capitanchik <contact@louiscap.co>
Date: Fri, 13 Jan 2023 23:56:40 +0000
Subject: [PATCH] Add duration_since_epoch method to Spot

---
 Cargo.toml             |  2 +-
 rustfmt.toml           |  4 ++++
 src/instant_desktop.rs | 20 +++++++++++++++++---
 src/instant_web.rs     | 43 ++++++++++++++++++++++++++++++++++--------
 src/lib.rs             | 23 ++++++++++++----------
 5 files changed, 70 insertions(+), 22 deletions(-)
 create mode 100644 rustfmt.toml

diff --git a/Cargo.toml b/Cargo.toml
index 96bbc3f..59c2022 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "web_instant"
-version = "0.2.1"
+version = "0.3.0"
 edition = "2021"
 description = "Cross platform impl of Instant"
 authors = [
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..d62aed7
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,4 @@
+hard_tabs = true
+#group_imports = "StdExternalCrate"
+use_field_init_shorthand = true
+use_try_shorthand = true
\ No newline at end of file
diff --git a/src/instant_desktop.rs b/src/instant_desktop.rs
index 3c9a723..2888cc1 100644
--- a/src/instant_desktop.rs
+++ b/src/instant_desktop.rs
@@ -1,6 +1,6 @@
 use std::fmt::{Debug, Formatter};
 use std::ops::{Add, AddAssign, Sub, SubAssign};
-use std::time::{Duration, Instant};
+use std::time::{Duration, Instant, SystemTime};
 
 #[allow(clippy::derive_partial_eq_without_eq)]
 #[derive(Copy, Clone, PartialEq, PartialOrd)]
@@ -54,6 +54,18 @@ impl Spot {
 	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 {
@@ -64,7 +76,8 @@ impl Add<Duration> for Spot {
 	/// 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")
+		self.checked_add(other)
+			.expect("overflow when adding duration to instant")
 	}
 }
 
@@ -78,7 +91,8 @@ 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")
+		self.checked_sub(other)
+			.expect("overflow when subtracting duration from instant")
 	}
 }
 
diff --git a/src/instant_web.rs b/src/instant_web.rs
index 9a6439d..88f5265 100644
--- a/src/instant_web.rs
+++ b/src/instant_web.rs
@@ -1,6 +1,6 @@
 use std::fmt::{Debug, Formatter};
 use std::ops::{Add, AddAssign, Sub, SubAssign};
-use std::time::Duration;
+use std::time::{Duration, Instant};
 
 #[derive(Copy, Clone, PartialEq, PartialOrd)]
 pub struct Spot {
@@ -27,7 +27,10 @@ impl Spot {
 	/// 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()
+		match self.checked_duration_since(earlier) {
+			Some(duration) => duration,
+			None => std::process::abort(),
+		}
 	}
 	/// Returns the amount of time elapsed from another instant to this one,
 	/// or None if that instant is later than this one.
@@ -45,14 +48,19 @@ impl Spot {
 	/// 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.checked_duration_since(earlier).unwrap_or_default()
+		match self.checked_duration_since(earlier) {
+			Some(duration) => duration,
+			None => std::process::abort(),
+		}
 	}
 	/// 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> {
 		let duration_millis = duration.as_secs_f64() / 1000.0;
-		Some(Spot { inner: self.inner + duration_millis })
+		Some(Spot {
+			inner: self.inner + duration_millis,
+		})
 	}
 	/// 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`
@@ -62,9 +70,17 @@ impl Spot {
 		if duration_millis > self.inner {
 			None
 		} else {
-			Some(Spot { inner: self.inner - duration_millis })
+			Some(Spot {
+				inner: self.inner - duration_millis,
+			})
 		}
 	}
+
+	/// 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 {
+		self.duration_since(Spot { inner: 0.0 })
+	}
 }
 
 impl Add<Duration> for Spot {
@@ -75,7 +91,13 @@ impl Add<Duration> for Spot {
 	/// 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")
+		match self.checked_add(other) {
+			Some(duration) => duration,
+			None => {
+				eprint!("overflow when adding duration to instant");
+				std::process::abort();
+			}
+		}
 	}
 }
 
@@ -89,7 +111,13 @@ 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")
+		match self.checked_sub(other) {
+			Some(duration) => duration,
+			None => {
+				eprintln!("overflow when subtracting duration from instant");
+				std::process::abort();
+			}
+		}
 	}
 }
 
@@ -99,7 +127,6 @@ impl SubAssign<Duration> for Spot {
 	}
 }
 
-
 impl Sub<Spot> for Spot {
 	type Output = Duration;
 
diff --git a/src/lib.rs b/src/lib.rs
index 8e11342..282860d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,20 +1,23 @@
 //! # Web Instant
-//! 
-//! Provides `Spot`, a version of `Instant` that works both in environments that support `Instant` and `wasm` family targets. On desktop, the internal representation uses `std::time::Instant`. On the web, the internal representation is an `f64`,
-//! and uses `js_sys::Date` methods to cover functinality where required
-//! 
-//! All the methods on `Instant` are implemented for `Spot`, so you can just replace uses of `std::time::Instant` with `web_instant::Spot`
-//! 
+//!
+//! Provides `Spot`, a version of `Instant` that works both in environments that support `Instant` and
+//! `wasm` family targets. On desktop, the internal representation uses `std::time::Instant`. On the
+//! web, the internal representation is an `f64`, and uses `js_sys::Date` methods to cover
+//! functionality where required
+//!
+//! All the methods on `Instant` are implemented for `Spot`, so you can just replace uses of
+//! `std::time::Instant` with `web_instant::Spot`
+//!
 //! ## Install
-//! 
+//!
 //! `cargo add web_instant`
-//! 
+//!
 //! ## Usage
-//! 
+//!
 //! ```rust
 //! use web_instant::Spot;
 //! use std::time::Duration;
-//! 
+//!
 //! fn my_cross_platform_timer(last_time: Spot) {
 //! 	let time_diff: Duration = Spot::now() - last_time;
 //! 	println!("It has been {} seconds", time_diff.as_secs());
-- 
GitLab