Ronald Kinard
8 years ago
committed by
GitHub
5 changed files with 1215 additions and 2 deletions
@ -0,0 +1,270 @@ |
|||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use cmp::Ordering; |
||||||
|
use libc; |
||||||
|
use time::Duration; |
||||||
|
|
||||||
|
pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; |
||||||
|
|
||||||
|
const NSEC_PER_SEC: u64 = 1_000_000_000; |
||||||
|
|
||||||
|
#[derive(Copy, Clone)] |
||||||
|
struct Timespec { |
||||||
|
t: libc::timespec, |
||||||
|
} |
||||||
|
|
||||||
|
impl Timespec { |
||||||
|
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { |
||||||
|
if self >= other { |
||||||
|
Ok(if self.t.tv_nsec >= other.t.tv_nsec { |
||||||
|
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, |
||||||
|
(self.t.tv_nsec - other.t.tv_nsec) as u32) |
||||||
|
} else { |
||||||
|
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, |
||||||
|
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - |
||||||
|
other.t.tv_nsec as u32) |
||||||
|
}) |
||||||
|
} else { |
||||||
|
match other.sub_timespec(self) { |
||||||
|
Ok(d) => Err(d), |
||||||
|
Err(d) => Ok(d), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn add_duration(&self, other: &Duration) -> Timespec { |
||||||
|
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); |
||||||
|
let mut secs = secs.expect("overflow when adding duration to time"); |
||||||
|
|
||||||
|
// Nano calculations can't overflow because nanos are <1B which fit
|
||||||
|
// in a u32.
|
||||||
|
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; |
||||||
|
if nsec >= NSEC_PER_SEC as u32 { |
||||||
|
nsec -= NSEC_PER_SEC as u32; |
||||||
|
secs = secs.checked_add(1).expect("overflow when adding \ |
||||||
|
duration to time"); |
||||||
|
} |
||||||
|
Timespec { |
||||||
|
t: libc::timespec { |
||||||
|
tv_sec: secs as libc::time_t, |
||||||
|
tv_nsec: nsec as libc::c_long, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn sub_duration(&self, other: &Duration) -> Timespec { |
||||||
|
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); |
||||||
|
let mut secs = secs.expect("overflow when subtracting duration \ |
||||||
|
from time"); |
||||||
|
|
||||||
|
// Similar to above, nanos can't overflow.
|
||||||
|
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; |
||||||
|
if nsec < 0 { |
||||||
|
nsec += NSEC_PER_SEC as i32; |
||||||
|
secs = secs.checked_sub(1).expect("overflow when subtracting \ |
||||||
|
duration from time"); |
||||||
|
} |
||||||
|
Timespec { |
||||||
|
t: libc::timespec { |
||||||
|
tv_sec: secs as libc::time_t, |
||||||
|
tv_nsec: nsec as libc::c_long, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl PartialEq for Timespec { |
||||||
|
fn eq(&self, other: &Timespec) -> bool { |
||||||
|
self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Eq for Timespec {} |
||||||
|
|
||||||
|
impl PartialOrd for Timespec { |
||||||
|
fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> { |
||||||
|
Some(self.cmp(other)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Ord for Timespec { |
||||||
|
fn cmp(&self, other: &Timespec) -> Ordering { |
||||||
|
let me = (self.t.tv_sec, self.t.tv_nsec); |
||||||
|
let other = (other.t.tv_sec, other.t.tv_nsec); |
||||||
|
me.cmp(&other) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
mod inner { |
||||||
|
use fmt; |
||||||
|
use libc; |
||||||
|
use sys::cvt; |
||||||
|
use sys_common::mul_div_u64; |
||||||
|
use time::Duration; |
||||||
|
|
||||||
|
use super::NSEC_PER_SEC; |
||||||
|
use super::Timespec; |
||||||
|
|
||||||
|
use spin; |
||||||
|
use libctru; |
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] |
||||||
|
pub struct Instant { |
||||||
|
t: u64 |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||||
|
pub struct SystemTime { |
||||||
|
t: Timespec, |
||||||
|
} |
||||||
|
|
||||||
|
pub const UNIX_EPOCH: SystemTime = SystemTime { |
||||||
|
t: Timespec { |
||||||
|
t: libc::timespec { |
||||||
|
tv_sec: 0, |
||||||
|
tv_nsec: 0, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
impl Instant { |
||||||
|
pub fn now() -> Instant { |
||||||
|
Instant { t: ctr_absolute_time() } |
||||||
|
} |
||||||
|
|
||||||
|
pub fn sub_instant(&self, other: &Instant) -> Duration { |
||||||
|
let info = info(); |
||||||
|
let diff = self.t.checked_sub(other.t) |
||||||
|
.expect("second instant is later than self"); |
||||||
|
let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64); |
||||||
|
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn add_duration(&self, other: &Duration) -> Instant { |
||||||
|
Instant { |
||||||
|
t: self.t.checked_add(dur2intervals(other)) |
||||||
|
.expect("overflow when adding duration to instant"), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn sub_duration(&self, other: &Duration) -> Instant { |
||||||
|
Instant { |
||||||
|
t: self.t.checked_sub(dur2intervals(other)) |
||||||
|
.expect("overflow when adding duration to instant"), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// The initial system tick after which all Instants occur
|
||||||
|
static TICK: spin::Once<u64> = spin::Once::new(); |
||||||
|
|
||||||
|
// A source of monotonic time based on ticks of the 3DS CPU. Returns the
|
||||||
|
// number of system ticks elapsed since an arbitrary point in the past
|
||||||
|
fn ctr_absolute_time() -> u64 { |
||||||
|
let first_tick = get_first_tick(); |
||||||
|
let current_tick = get_system_tick(); |
||||||
|
current_tick - first_tick |
||||||
|
} |
||||||
|
|
||||||
|
// The first time this function is called, it generates and returns the
|
||||||
|
// initial system tick used to create Instants
|
||||||
|
//
|
||||||
|
// subsequent calls to this function return the previously generated
|
||||||
|
// tick value
|
||||||
|
fn get_first_tick() -> u64 { |
||||||
|
*TICK.call_once(get_system_tick) |
||||||
|
} |
||||||
|
|
||||||
|
// Gets the current system tick
|
||||||
|
#[inline] |
||||||
|
fn get_system_tick() -> u64 { |
||||||
|
unsafe { libctru::svc::svcGetSystemTick() } |
||||||
|
} |
||||||
|
|
||||||
|
// A struct representing the clock speed of the 3DS
|
||||||
|
struct CtrClockInfo { |
||||||
|
numer: u32, |
||||||
|
denom: u32, |
||||||
|
} |
||||||
|
|
||||||
|
// Initializes the CtrClockInfo struct
|
||||||
|
//
|
||||||
|
// Note that svcGetSystemTick always runs at 268MHz (268,111,856Hz), even
|
||||||
|
// on a New 3DS running in 804MHz mode
|
||||||
|
//
|
||||||
|
// See https://www.3dbrew.org/wiki/Hardware#Common_hardware
|
||||||
|
fn info() -> CtrClockInfo { |
||||||
|
CtrClockInfo { |
||||||
|
numer: 1_000_000_000, |
||||||
|
denom: 268_111_856, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn dur2intervals(dur: &Duration) -> u64 { |
||||||
|
let info = info(); |
||||||
|
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { |
||||||
|
nanos.checked_add(dur.subsec_nanos() as u64) |
||||||
|
}).expect("overflow converting duration to nanoseconds"); |
||||||
|
mul_div_u64(nanos, info.denom as u64, info.numer as u64) |
||||||
|
} |
||||||
|
|
||||||
|
impl SystemTime { |
||||||
|
pub fn now() -> SystemTime { |
||||||
|
use ptr; |
||||||
|
|
||||||
|
let mut s = libc::timeval { |
||||||
|
tv_sec: 0, |
||||||
|
tv_usec: 0, |
||||||
|
}; |
||||||
|
cvt(unsafe { |
||||||
|
libc::gettimeofday(&mut s, ptr::null_mut()) |
||||||
|
}).unwrap(); |
||||||
|
return SystemTime::from(s) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn sub_time(&self, other: &SystemTime) |
||||||
|
-> Result<Duration, Duration> { |
||||||
|
self.t.sub_timespec(&other.t) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn add_duration(&self, other: &Duration) -> SystemTime { |
||||||
|
SystemTime { t: self.t.add_duration(other) } |
||||||
|
} |
||||||
|
|
||||||
|
pub fn sub_duration(&self, other: &Duration) -> SystemTime { |
||||||
|
SystemTime { t: self.t.sub_duration(other) } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<libc::timeval> for SystemTime { |
||||||
|
fn from(t: libc::timeval) -> SystemTime { |
||||||
|
SystemTime::from(libc::timespec { |
||||||
|
tv_sec: t.tv_sec, |
||||||
|
tv_nsec: (t.tv_usec * 1000) as libc::c_long, |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl From<libc::timespec> for SystemTime { |
||||||
|
fn from(t: libc::timespec) -> SystemTime { |
||||||
|
SystemTime { t: Timespec { t: t } } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl fmt::Debug for SystemTime { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
f.debug_struct("SystemTime") |
||||||
|
.field("tv_sec", &self.t.t.tv_sec) |
||||||
|
.field("tv_nsec", &self.t.t.tv_nsec) |
||||||
|
.finish() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,420 @@ |
|||||||
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign}; |
||||||
|
|
||||||
|
const NANOS_PER_SEC: u32 = 1_000_000_000; |
||||||
|
const NANOS_PER_MILLI: u32 = 1_000_000; |
||||||
|
const MILLIS_PER_SEC: u64 = 1_000; |
||||||
|
|
||||||
|
/// A duration type to represent a span of time, typically used for system
|
||||||
|
/// timeouts.
|
||||||
|
///
|
||||||
|
/// Each duration is composed of a number of seconds and nanosecond precision.
|
||||||
|
/// APIs binding a system timeout will typically round up the nanosecond
|
||||||
|
/// precision if the underlying system does not support that level of precision.
|
||||||
|
///
|
||||||
|
/// Durations implement many common traits, including `Add`, `Sub`, and other
|
||||||
|
/// ops traits. Currently a duration may only be inspected for its number of
|
||||||
|
/// seconds and its nanosecond precision.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// let five_seconds = Duration::new(5, 0);
|
||||||
|
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
|
||||||
|
///
|
||||||
|
/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
|
||||||
|
/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
|
||||||
|
///
|
||||||
|
/// let ten_millis = Duration::from_millis(10);
|
||||||
|
/// ```
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)] |
||||||
|
pub struct Duration { |
||||||
|
secs: u64, |
||||||
|
nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
|
||||||
|
} |
||||||
|
|
||||||
|
impl Duration { |
||||||
|
/// Creates a new `Duration` from the specified number of seconds and
|
||||||
|
/// additional nanosecond precision.
|
||||||
|
///
|
||||||
|
/// If the nanoseconds is greater than 1 billion (the number of nanoseconds
|
||||||
|
/// in a second), then it will carry over into the seconds provided.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This constructor will panic if the carry from the nanoseconds overflows
|
||||||
|
/// the seconds counter.
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[inline] |
||||||
|
pub fn new(secs: u64, nanos: u32) -> Duration { |
||||||
|
let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64) |
||||||
|
.expect("overflow in Duration::new"); |
||||||
|
let nanos = nanos % NANOS_PER_SEC; |
||||||
|
Duration { secs: secs, nanos: nanos } |
||||||
|
} |
||||||
|
|
||||||
|
/// Creates a new `Duration` from the specified number of seconds.
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[inline] |
||||||
|
pub fn from_secs(secs: u64) -> Duration { |
||||||
|
Duration { secs: secs, nanos: 0 } |
||||||
|
} |
||||||
|
|
||||||
|
/// Creates a new `Duration` from the specified number of milliseconds.
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[inline] |
||||||
|
pub fn from_millis(millis: u64) -> Duration { |
||||||
|
let secs = millis / MILLIS_PER_SEC; |
||||||
|
let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI; |
||||||
|
Duration { secs: secs, nanos: nanos } |
||||||
|
} |
||||||
|
|
||||||
|
/// Returns the number of whole seconds represented by this duration.
|
||||||
|
///
|
||||||
|
/// The extra precision represented by this duration is ignored (i.e. extra
|
||||||
|
/// nanoseconds are not represented in the returned value).
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[inline] |
||||||
|
pub fn as_secs(&self) -> u64 { self.secs } |
||||||
|
|
||||||
|
/// Returns the nanosecond precision represented by this duration.
|
||||||
|
///
|
||||||
|
/// This method does **not** return the length of the duration when
|
||||||
|
/// represented by nanoseconds. The returned number always represents a
|
||||||
|
/// fractional portion of a second (i.e. it is less than one billion).
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
#[inline] |
||||||
|
pub fn subsec_nanos(&self) -> u32 { self.nanos } |
||||||
|
|
||||||
|
/// Checked duration addition. Computes `self + other`, returning `None`
|
||||||
|
/// if overflow occurred.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(duration_checked_ops)]
|
||||||
|
///
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
|
||||||
|
/// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||||
|
#[inline] |
||||||
|
pub fn checked_add(self, rhs: Duration) -> Option<Duration> { |
||||||
|
if let Some(mut secs) = self.secs.checked_add(rhs.secs) { |
||||||
|
let mut nanos = self.nanos + rhs.nanos; |
||||||
|
if nanos >= NANOS_PER_SEC { |
||||||
|
nanos -= NANOS_PER_SEC; |
||||||
|
if let Some(new_secs) = secs.checked_add(1) { |
||||||
|
secs = new_secs; |
||||||
|
} else { |
||||||
|
return None; |
||||||
|
} |
||||||
|
} |
||||||
|
debug_assert!(nanos < NANOS_PER_SEC); |
||||||
|
Some(Duration { |
||||||
|
secs: secs, |
||||||
|
nanos: nanos, |
||||||
|
}) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Checked duration subtraction. Computes `self + other`, returning `None`
|
||||||
|
/// if the result would be negative or if underflow occurred.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(duration_checked_ops)]
|
||||||
|
///
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
|
||||||
|
/// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||||
|
#[inline] |
||||||
|
pub fn checked_sub(self, rhs: Duration) -> Option<Duration> { |
||||||
|
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { |
||||||
|
let nanos = if self.nanos >= rhs.nanos { |
||||||
|
self.nanos - rhs.nanos |
||||||
|
} else { |
||||||
|
if let Some(sub_secs) = secs.checked_sub(1) { |
||||||
|
secs = sub_secs; |
||||||
|
self.nanos + NANOS_PER_SEC - rhs.nanos |
||||||
|
} else { |
||||||
|
return None; |
||||||
|
} |
||||||
|
}; |
||||||
|
debug_assert!(nanos < NANOS_PER_SEC); |
||||||
|
Some(Duration { secs: secs, nanos: nanos }) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Checked duration multiplication. Computes `self * other`, returning
|
||||||
|
/// `None` if underflow or overflow occurred.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(duration_checked_ops)]
|
||||||
|
///
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
|
||||||
|
/// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||||
|
#[inline] |
||||||
|
pub fn checked_mul(self, rhs: u32) -> Option<Duration> { |
||||||
|
// Multiply nanoseconds as u64, because it cannot overflow that way.
|
||||||
|
let total_nanos = self.nanos as u64 * rhs as u64; |
||||||
|
let extra_secs = total_nanos / (NANOS_PER_SEC as u64); |
||||||
|
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; |
||||||
|
if let Some(secs) = self.secs |
||||||
|
.checked_mul(rhs as u64) |
||||||
|
.and_then(|s| s.checked_add(extra_secs)) { |
||||||
|
debug_assert!(nanos < NANOS_PER_SEC); |
||||||
|
Some(Duration { |
||||||
|
secs: secs, |
||||||
|
nanos: nanos, |
||||||
|
}) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Checked duration division. Computes `self / other`, returning `None`
|
||||||
|
/// if `other == 0` or the operation results in underflow or overflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(duration_checked_ops)]
|
||||||
|
///
|
||||||
|
/// use std::time::Duration;
|
||||||
|
///
|
||||||
|
/// assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
|
||||||
|
/// assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
|
||||||
|
/// assert_eq!(Duration::new(2, 0).checked_div(0), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "duration_checked_ops", issue = "35774")] |
||||||
|
#[inline] |
||||||
|
pub fn checked_div(self, rhs: u32) -> Option<Duration> { |
||||||
|
if rhs != 0 { |
||||||
|
let secs = self.secs / (rhs as u64); |
||||||
|
let carry = self.secs - secs * (rhs as u64); |
||||||
|
let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); |
||||||
|
let nanos = self.nanos / rhs + (extra_nanos as u32); |
||||||
|
debug_assert!(nanos < NANOS_PER_SEC); |
||||||
|
Some(Duration { secs: secs, nanos: nanos }) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
impl Add for Duration { |
||||||
|
type Output = Duration; |
||||||
|
|
||||||
|
fn add(self, rhs: Duration) -> Duration { |
||||||
|
self.checked_add(rhs).expect("overflow when adding durations") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl AddAssign for Duration { |
||||||
|
fn add_assign(&mut self, rhs: Duration) { |
||||||
|
*self = *self + rhs; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
impl Sub for Duration { |
||||||
|
type Output = Duration; |
||||||
|
|
||||||
|
fn sub(self, rhs: Duration) -> Duration { |
||||||
|
self.checked_sub(rhs).expect("overflow when subtracting durations") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl SubAssign for Duration { |
||||||
|
fn sub_assign(&mut self, rhs: Duration) { |
||||||
|
*self = *self - rhs; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
impl Mul<u32> for Duration { |
||||||
|
type Output = Duration; |
||||||
|
|
||||||
|
fn mul(self, rhs: u32) -> Duration { |
||||||
|
self.checked_mul(rhs).expect("overflow when multiplying duration by scalar") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl MulAssign<u32> for Duration { |
||||||
|
fn mul_assign(&mut self, rhs: u32) { |
||||||
|
*self = *self * rhs; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "duration", since = "1.3.0")] |
||||||
|
impl Div<u32> for Duration { |
||||||
|
type Output = Duration; |
||||||
|
|
||||||
|
fn div(self, rhs: u32) -> Duration { |
||||||
|
self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl DivAssign<u32> for Duration { |
||||||
|
fn div_assign(&mut self, rhs: u32) { |
||||||
|
*self = *self / rhs; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::Duration; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn creation() { |
||||||
|
assert!(Duration::from_secs(1) != Duration::from_secs(0)); |
||||||
|
assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), |
||||||
|
Duration::from_secs(3)); |
||||||
|
assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), |
||||||
|
Duration::new(4, 10 * 1_000_000)); |
||||||
|
assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn secs() { |
||||||
|
assert_eq!(Duration::new(0, 0).as_secs(), 0); |
||||||
|
assert_eq!(Duration::from_secs(1).as_secs(), 1); |
||||||
|
assert_eq!(Duration::from_millis(999).as_secs(), 0); |
||||||
|
assert_eq!(Duration::from_millis(1001).as_secs(), 1); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn nanos() { |
||||||
|
assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); |
||||||
|
assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); |
||||||
|
assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); |
||||||
|
assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); |
||||||
|
assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); |
||||||
|
assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn add() { |
||||||
|
assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), |
||||||
|
Duration::new(0, 1)); |
||||||
|
assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), |
||||||
|
Duration::new(1, 1)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn checked_add() { |
||||||
|
assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), |
||||||
|
Some(Duration::new(0, 1))); |
||||||
|
assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), |
||||||
|
Some(Duration::new(1, 1))); |
||||||
|
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn sub() { |
||||||
|
assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), |
||||||
|
Duration::new(0, 1)); |
||||||
|
assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), |
||||||
|
Duration::new(0, 1)); |
||||||
|
assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), |
||||||
|
Duration::new(0, 999_999_999)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn checked_sub() { |
||||||
|
let zero = Duration::new(0, 0); |
||||||
|
let one_nano = Duration::new(0, 1); |
||||||
|
let one_sec = Duration::new(1, 0); |
||||||
|
assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); |
||||||
|
assert_eq!(one_sec.checked_sub(one_nano), |
||||||
|
Some(Duration::new(0, 999_999_999))); |
||||||
|
assert_eq!(zero.checked_sub(one_nano), None); |
||||||
|
assert_eq!(zero.checked_sub(one_sec), None); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] #[should_panic] |
||||||
|
fn sub_bad1() { |
||||||
|
Duration::new(0, 0) - Duration::new(0, 1); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] #[should_panic] |
||||||
|
fn sub_bad2() { |
||||||
|
Duration::new(0, 0) - Duration::new(1, 0); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn mul() { |
||||||
|
assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); |
||||||
|
assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); |
||||||
|
assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); |
||||||
|
assert_eq!(Duration::new(0, 500_000_001) * 4000, |
||||||
|
Duration::new(2000, 4000)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn checked_mul() { |
||||||
|
assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); |
||||||
|
assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); |
||||||
|
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); |
||||||
|
assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), |
||||||
|
Some(Duration::new(2000, 4000))); |
||||||
|
assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn div() { |
||||||
|
assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); |
||||||
|
assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); |
||||||
|
assert_eq!(Duration::new(99, 999_999_000) / 100, |
||||||
|
Duration::new(0, 999_999_990)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn checked_div() { |
||||||
|
assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); |
||||||
|
assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); |
||||||
|
assert_eq!(Duration::new(2, 0).checked_div(0), None); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,447 @@ |
|||||||
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Temporal quantification.
|
||||||
|
//!
|
||||||
|
//! Example:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use std::time::Duration;
|
||||||
|
//!
|
||||||
|
//! let five_seconds = Duration::new(5, 0);
|
||||||
|
//! // both declarations are equivalent
|
||||||
|
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
#![stable(feature = "time", since = "1.3.0")] |
||||||
|
|
||||||
|
use error::Error; |
||||||
|
use fmt; |
||||||
|
use ops::{Add, Sub, AddAssign, SubAssign}; |
||||||
|
use sys::time; |
||||||
|
use sys_common::FromInner; |
||||||
|
|
||||||
|
#[stable(feature = "time", since = "1.3.0")] |
||||||
|
pub use self::duration::Duration; |
||||||
|
|
||||||
|
mod duration; |
||||||
|
|
||||||
|
/// A measurement of a monotonically increasing clock.
|
||||||
|
/// Opaque and useful only with `Duration`.
|
||||||
|
///
|
||||||
|
/// Instants are always guaranteed to be greater than any previously measured
|
||||||
|
/// instant when created, and are often useful for tasks such as measuring
|
||||||
|
/// benchmarks or timing how long an operation takes.
|
||||||
|
///
|
||||||
|
/// Note, however, that instants are not guaranteed to be **steady**. In other
|
||||||
|
/// words, each tick of the underlying clock may not be the same length (e.g.
|
||||||
|
/// some seconds may be longer than others). An instant may jump forwards or
|
||||||
|
/// experience time dilation (slow down or speed up), but it will never go
|
||||||
|
/// backwards.
|
||||||
|
///
|
||||||
|
/// Instants are opaque types that can only be compared to one another. There is
|
||||||
|
/// no method to get "the number of seconds" from an instant. Instead, it only
|
||||||
|
/// allows measuring the duration between two instants (or comparing two
|
||||||
|
/// instants).
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::time::{Duration, Instant};
|
||||||
|
/// use std::thread::sleep;
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let now = Instant::now();
|
||||||
|
///
|
||||||
|
/// // we sleep for 2 seconds
|
||||||
|
/// sleep(Duration::new(2, 0));
|
||||||
|
/// // it prints '2'
|
||||||
|
/// println!("{}", now.elapsed().as_secs());
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub struct Instant(time::Instant); |
||||||
|
|
||||||
|
/// A measurement of the system clock, useful for talking to
|
||||||
|
/// external entities like the file system or other processes.
|
||||||
|
///
|
||||||
|
/// Distinct from the `Instant` type, this time measurement **is not
|
||||||
|
/// monotonic**. This means that you can save a file to the file system, then
|
||||||
|
/// save another file to the file system, **and the second file has a
|
||||||
|
/// `SystemTime` measurement earlier than the first**. In other words, an
|
||||||
|
/// operation that happens after another operation in real time may have an
|
||||||
|
/// earlier `SystemTime`!
|
||||||
|
///
|
||||||
|
/// Consequently, comparing two `SystemTime` instances to learn about the
|
||||||
|
/// duration between them returns a `Result` instead of an infallible `Duration`
|
||||||
|
/// to indicate that this sort of time drift may happen and needs to be handled.
|
||||||
|
///
|
||||||
|
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
|
||||||
|
/// constant is provided in this module as an anchor in time to learn
|
||||||
|
/// information about a `SystemTime`. By calculating the duration from this
|
||||||
|
/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
|
||||||
|
/// or perhaps some other string representation.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::time::{Duration, SystemTime};
|
||||||
|
/// use std::thread::sleep;
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let now = SystemTime::now();
|
||||||
|
///
|
||||||
|
/// // we sleep for 2 seconds
|
||||||
|
/// sleep(Duration::new(2, 0));
|
||||||
|
/// match now.elapsed() {
|
||||||
|
/// Ok(elapsed) => {
|
||||||
|
/// // it prints '2'
|
||||||
|
/// println!("{}", elapsed.as_secs());
|
||||||
|
/// }
|
||||||
|
/// Err(e) => {
|
||||||
|
/// // an error occured!
|
||||||
|
/// println!("Error: {:?}", e);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] |
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub struct SystemTime(time::SystemTime); |
||||||
|
|
||||||
|
/// An error returned from the `duration_since` method on `SystemTime`,
|
||||||
|
/// used to learn how far in the opposite direction a system time lies.
|
||||||
|
#[derive(Clone, Debug)] |
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub struct SystemTimeError(Duration); |
||||||
|
|
||||||
|
impl Instant { |
||||||
|
/// Returns an instant corresponding to "now".
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn now() -> Instant { |
||||||
|
Instant(time::Instant::now()) |
||||||
|
} |
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from another instant to this one.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function will panic if `earlier` is later than `self`, which should
|
||||||
|
/// only be possible if `earlier` was created after `self`. Because
|
||||||
|
/// `Instant` is monotonic, the only time that this should happen should be
|
||||||
|
/// a bug.
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn duration_since(&self, earlier: Instant) -> Duration { |
||||||
|
self.0.sub_instant(&earlier.0) |
||||||
|
} |
||||||
|
|
||||||
|
/// Returns the amount of time elapsed since this instant was created.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function may panic if the current time is earlier than this
|
||||||
|
/// instant, which is something that can happen if an `Instant` is
|
||||||
|
/// produced synthetically.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::thread::sleep;
|
||||||
|
/// use std::time::{Duration, Instant};
|
||||||
|
///
|
||||||
|
/// let instant = Instant::now();
|
||||||
|
/// let three_secs = Duration::from_secs(3);
|
||||||
|
/// sleep(three_secs);
|
||||||
|
/// assert!(instant.elapsed() >= three_secs);
|
||||||
|
/// ```
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn elapsed(&self) -> Duration { |
||||||
|
Instant::now() - *self |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Add<Duration> for Instant { |
||||||
|
type Output = Instant; |
||||||
|
|
||||||
|
fn add(self, other: Duration) -> Instant { |
||||||
|
Instant(self.0.add_duration(&other)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl AddAssign<Duration> for Instant { |
||||||
|
fn add_assign(&mut self, other: Duration) { |
||||||
|
*self = *self + other; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Sub<Duration> for Instant { |
||||||
|
type Output = Instant; |
||||||
|
|
||||||
|
fn sub(self, other: Duration) -> Instant { |
||||||
|
Instant(self.0.sub_duration(&other)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl SubAssign<Duration> for Instant { |
||||||
|
fn sub_assign(&mut self, other: Duration) { |
||||||
|
*self = *self - other; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Sub<Instant> for Instant { |
||||||
|
type Output = Duration; |
||||||
|
|
||||||
|
fn sub(self, other: Instant) -> Duration { |
||||||
|
self.duration_since(other) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl fmt::Debug for Instant { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
self.0.fmt(f) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl SystemTime { |
||||||
|
/// Returns the system time corresponding to "now".
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn now() -> SystemTime { |
||||||
|
SystemTime(time::SystemTime::now()) |
||||||
|
} |
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from an earlier point in time.
|
||||||
|
///
|
||||||
|
/// This function may fail because measurements taken earlier are not
|
||||||
|
/// guaranteed to always be before later measurements (due to anomalies such
|
||||||
|
/// as the system clock being adjusted either forwards or backwards).
|
||||||
|
///
|
||||||
|
/// If successful, `Ok(Duration)` is returned where the duration represents
|
||||||
|
/// the amount of time elapsed from the specified measurement to this one.
|
||||||
|
///
|
||||||
|
/// Returns an `Err` if `earlier` is later than `self`, and the error
|
||||||
|
/// contains how far from `self` the time is.
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn duration_since(&self, earlier: SystemTime) |
||||||
|
-> Result<Duration, SystemTimeError> { |
||||||
|
self.0.sub_time(&earlier.0).map_err(SystemTimeError) |
||||||
|
} |
||||||
|
|
||||||
|
/// Returns the amount of time elapsed since this system time was created.
|
||||||
|
///
|
||||||
|
/// This function may fail as the underlying system clock is susceptible to
|
||||||
|
/// drift and updates (e.g. the system clock could go backwards), so this
|
||||||
|
/// function may not always succeed. If successful, `Ok(duration)` is
|
||||||
|
/// returned where the duration represents the amount of time elapsed from
|
||||||
|
/// this time measurement to the current time.
|
||||||
|
///
|
||||||
|
/// Returns an `Err` if `self` is later than the current system time, and
|
||||||
|
/// the error contains how far from the current system time `self` is.
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> { |
||||||
|
SystemTime::now().duration_since(*self) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Add<Duration> for SystemTime { |
||||||
|
type Output = SystemTime; |
||||||
|
|
||||||
|
fn add(self, dur: Duration) -> SystemTime { |
||||||
|
SystemTime(self.0.add_duration(&dur)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl AddAssign<Duration> for SystemTime { |
||||||
|
fn add_assign(&mut self, other: Duration) { |
||||||
|
*self = *self + other; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Sub<Duration> for SystemTime { |
||||||
|
type Output = SystemTime; |
||||||
|
|
||||||
|
fn sub(self, dur: Duration) -> SystemTime { |
||||||
|
SystemTime(self.0.sub_duration(&dur)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time_augmented_assignment", since = "1.9.0")] |
||||||
|
impl SubAssign<Duration> for SystemTime { |
||||||
|
fn sub_assign(&mut self, other: Duration) { |
||||||
|
*self = *self - other; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl fmt::Debug for SystemTime { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
self.0.fmt(f) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// An anchor in time which can be used to create new `SystemTime` instances or
|
||||||
|
/// learn about where in time a `SystemTime` lies.
|
||||||
|
///
|
||||||
|
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
|
||||||
|
/// respect to the system clock. Using `duration_since` on an existing
|
||||||
|
/// `SystemTime` instance can tell how far away from this point in time a
|
||||||
|
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
|
||||||
|
/// `SystemTime` instance to represent another fixed point in time.
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); |
||||||
|
|
||||||
|
impl SystemTimeError { |
||||||
|
/// Returns the positive duration which represents how far forward the
|
||||||
|
/// second system time was from the first.
|
||||||
|
///
|
||||||
|
/// A `SystemTimeError` is returned from the `duration_since`
|
||||||
|
/// operation whenever the second system time represents a point later
|
||||||
|
/// in time than the `self` of the method call.
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
pub fn duration(&self) -> Duration { |
||||||
|
self.0 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl Error for SystemTimeError { |
||||||
|
fn description(&self) -> &str { "other time was not earlier than self" } |
||||||
|
} |
||||||
|
|
||||||
|
#[stable(feature = "time2", since = "1.8.0")] |
||||||
|
impl fmt::Display for SystemTimeError { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
write!(f, "second time provided was later than self") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl FromInner<time::SystemTime> for SystemTime { |
||||||
|
fn from_inner(time: time::SystemTime) -> SystemTime { |
||||||
|
SystemTime(time) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; |
||||||
|
|
||||||
|
macro_rules! assert_almost_eq { |
||||||
|
($a:expr, $b:expr) => ({ |
||||||
|
let (a, b) = ($a, $b); |
||||||
|
if a != b { |
||||||
|
let (a, b) = if a > b {(a, b)} else {(b, a)}; |
||||||
|
assert!(a - Duration::new(0, 100) <= b); |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn instant_monotonic() { |
||||||
|
let a = Instant::now(); |
||||||
|
let b = Instant::now(); |
||||||
|
assert!(b >= a); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn instant_elapsed() { |
||||||
|
let a = Instant::now(); |
||||||
|
a.elapsed(); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn instant_math() { |
||||||
|
let a = Instant::now(); |
||||||
|
let b = Instant::now(); |
||||||
|
let dur = b.duration_since(a); |
||||||
|
assert_almost_eq!(b - dur, a); |
||||||
|
assert_almost_eq!(a + dur, b); |
||||||
|
|
||||||
|
let second = Duration::new(1, 0); |
||||||
|
assert_almost_eq!(a - second + second, a); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
#[should_panic] |
||||||
|
fn instant_duration_panic() { |
||||||
|
let a = Instant::now(); |
||||||
|
(a - Duration::new(1, 0)).duration_since(a); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn system_time_math() { |
||||||
|
let a = SystemTime::now(); |
||||||
|
let b = SystemTime::now(); |
||||||
|
match b.duration_since(a) { |
||||||
|
Ok(dur) if dur == Duration::new(0, 0) => { |
||||||
|
assert_almost_eq!(a, b); |
||||||
|
} |
||||||
|
Ok(dur) => { |
||||||
|
assert!(b > a); |
||||||
|
assert_almost_eq!(b - dur, a); |
||||||
|
assert_almost_eq!(a + dur, b); |
||||||
|
} |
||||||
|
Err(dur) => { |
||||||
|
let dur = dur.duration(); |
||||||
|
assert!(a > b); |
||||||
|
assert_almost_eq!(b + dur, a); |
||||||
|
assert_almost_eq!(b - dur, a); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let second = Duration::new(1, 0); |
||||||
|
assert_almost_eq!(a.duration_since(a - second).unwrap(), second); |
||||||
|
assert_almost_eq!(a.duration_since(a + second).unwrap_err() |
||||||
|
.duration(), second); |
||||||
|
|
||||||
|
assert_almost_eq!(a - second + second, a); |
||||||
|
|
||||||
|
let eighty_years = second * 60 * 60 * 24 * 365 * 80; |
||||||
|
assert_almost_eq!(a - eighty_years + eighty_years, a); |
||||||
|
assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a); |
||||||
|
|
||||||
|
let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); |
||||||
|
let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) |
||||||
|
+ Duration::new(0, 500_000_000); |
||||||
|
assert_eq!(one_second_from_epoch, one_second_from_epoch2); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn system_time_elapsed() { |
||||||
|
let a = SystemTime::now(); |
||||||
|
drop(a.elapsed()); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn since_epoch() { |
||||||
|
let ts = SystemTime::now(); |
||||||
|
let a = ts.duration_since(UNIX_EPOCH).unwrap(); |
||||||
|
let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap(); |
||||||
|
assert!(b > a); |
||||||
|
assert_eq!(b - a, Duration::new(1, 0)); |
||||||
|
|
||||||
|
// let's assume that we're all running computers later than 2000
|
||||||
|
let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30; |
||||||
|
assert!(a > thirty_years); |
||||||
|
|
||||||
|
// let's assume that we're all running computers earlier than 2090.
|
||||||
|
// Should give us ~70 years to fix this!
|
||||||
|
let hundred_twenty_years = thirty_years * 4; |
||||||
|
assert!(a < hundred_twenty_years); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue