Browse Source

time: Improve time types

 - Correct from_system_time implementation
 - Add missing functions and implementations to Instant type
 - Add missing frnction to Duration type

Closes: #141
Approved by: whitequark
Dan Robertson 7 years ago
parent
commit
2ea19084ea
1 changed files with 57 additions and 12 deletions
  1. 57 12
      src/time.rs

+ 57 - 12
src/time.rs

@@ -23,7 +23,7 @@ use core::{ops, fmt};
 ///   point.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Instant {
-    millis: i64,
+    pub millis: i64,
 }
 
 impl Instant {
@@ -32,17 +32,20 @@ impl Instant {
         Instant { millis }
     }
 
-    /// Create a new `Instant` from the current `SystemTime`.
-    #[cfg(feature = "std")]
-    pub fn now() -> Result<Instant, ::std::time::SystemTimeError> {
-        Self::from_system_time(::std::time::SystemTime::now())
+    /// Create a new `Instant` from a number of seconds.
+    pub fn from_secs(secs: i64) -> Instant {
+        Instant { millis: secs * 1000 }
     }
 
-    /// Create a new `Instant` from a `SystemTime`.
+    /// Create a new `Instant` from the current [std::time::SystemTime].
+    ///
+    /// See [std::time::SystemTime::now]
+    ///
+    /// [std::time::SystemTime]: https://doc.rust-lang.org/std/time/struct.SystemTime.html
+    /// [std::time::SystemTime::now]: https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.now
     #[cfg(feature = "std")]
-    pub fn from_system_time(time: ::std::time::SystemTime) -> Result<Instant, ::std::time::SystemTimeError> {
-        let n = ::std::time::UNIX_EPOCH.duration_since(time)?;
-        Ok(Self::from_millis(n.as_secs() as i64 * 1000 + (n.subsec_nanos() / 1_000_000) as i64))
+    pub fn now() -> Instant {
+        Self::from(::std::time::SystemTime::now())
     }
 
     /// The fractional number of milliseconds that have passed
@@ -64,6 +67,23 @@ impl Instant {
     }
 }
 
+#[cfg(feature = "std")]
+impl From<::std::time::Instant> for Instant {
+    fn from(other: ::std::time::Instant) -> Instant {
+        let elapsed = other.elapsed();
+        Instant::from_millis((elapsed.as_secs() * 1_000) as i64 + (elapsed.subsec_nanos() / 1_000_000) as i64)
+    }
+}
+
+#[cfg(feature = "std")]
+impl From<::std::time::SystemTime> for Instant {
+    fn from(other: ::std::time::SystemTime) -> Instant {
+        let n = other.duration_since(::std::time::UNIX_EPOCH)
+            .expect("start time must not be before the unix epoch");
+        Self::from_millis(n.as_secs() as i64 * 1000 + (n.subsec_nanos() / 1000000) as i64)
+    }
+}
+
 #[cfg(feature = "std")]
 impl Into<::std::time::SystemTime> for Instant {
     fn into(self) -> ::std::time::SystemTime {
@@ -85,6 +105,12 @@ impl ops::Add<Duration> for Instant {
     }
 }
 
+impl ops::AddAssign<Duration> for Instant {
+    fn add_assign(&mut self, rhs: Duration) {
+        self.millis += rhs.total_millis() as i64;
+    }
+}
+
 impl ops::Sub<Duration> for Instant {
     type Output = Instant;
 
@@ -93,10 +119,24 @@ impl ops::Sub<Duration> for Instant {
     }
 }
 
+impl ops::SubAssign<Duration> for Instant {
+    fn sub_assign(&mut self, rhs: Duration) {
+        self.millis -= rhs.total_millis() as i64;
+    }
+}
+
+impl ops::Sub<Instant> for Instant {
+    type Output = Duration;
+
+    fn sub(self, rhs: Instant) -> Duration {
+        Duration::from_millis((self.millis - rhs.millis).abs() as u64)
+    }
+}
+
 /// A relative amount of time.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Duration {
-    millis: u64,
+    pub millis: u64,
 }
 
 impl Duration {
@@ -105,6 +145,11 @@ impl Duration {
         Duration { millis }
     }
 
+    /// Create a new `Instant` from a number of seconds.
+    pub fn from_secs(secs: u64) -> Duration {
+        Duration { millis: secs * 1000 }
+    }
+
     /// The fractional number of milliseconds in this `Duration`.
     pub fn millis(&self) -> u64 {
         self.millis % 1000
@@ -233,7 +278,7 @@ mod test {
     #[cfg(feature = "std")]
     fn test_instant_conversions() {
         let mut epoc: ::std::time::SystemTime = Instant::from_millis(0).into();
-        assert_eq!(Instant::from_system_time(::std::time::UNIX_EPOCH).unwrap(),
+        assert_eq!(Instant::from(::std::time::UNIX_EPOCH),
                    Instant::from_millis(0));
         assert_eq!(epoc, ::std::time::UNIX_EPOCH);
         epoc = Instant::from_millis(2085955200 * 1000).into();