Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions library/std/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,56 @@ impl SystemTime {
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
self.0.checked_sub_duration(&duration).map(SystemTime)
}

/// Saturating [`SystemTime`] addition, computing `self + duration`,
/// returning [`SystemTime::MAX`] if overflow occurred.
///
/// In the case that the `duration` is smaller than the time precision of
/// the operating system, `self` will be returned.
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
pub fn saturating_add(&self, duration: Duration) -> SystemTime {
self.checked_add(duration).unwrap_or(SystemTime::MAX)
}

/// Saturating [`SystemTime`] subtraction, computing `self - duration`,
/// returning [`SystemTime::MIN`] if overflow occurred.
///
/// In the case that the `duration` is smaller than the time precision of
/// the operating system, `self` will be returned.
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
pub fn saturating_sub(&self, duration: Duration) -> SystemTime {
self.checked_sub(duration).unwrap_or(SystemTime::MIN)
}

/// Saturating computation of time elapsed from an earlier point in time,
/// returning [`Duration::ZERO`] in the case that `earlier` is later or
/// equal to `self`.
///
/// # Examples
///
/// ```no_run
/// #![feature(time_saturating_systemtime)]
/// use std::time::{Duration, SystemTime};
///
/// let now = SystemTime::now();
/// let prev = now.saturating_sub(Duration::new(1, 0));
///
/// // now - prev should return non-zero.
/// assert_eq!(now.saturating_duration_since(prev), Duration::new(1, 0));
/// assert!(now.duration_since(prev).is_ok());
///
/// // prev - now should return zero (and fail with the non-saturating).
/// assert_eq!(prev.saturating_duration_since(now), Duration::ZERO);
/// assert!(prev.duration_since(now).is_err());
///
/// // now - now should return zero (and work with the non-saturating).
/// assert_eq!(now.saturating_duration_since(now), Duration::ZERO);
/// assert!(now.duration_since(now).is_ok());
/// ```
#[unstable(feature = "time_saturating_systemtime", issue = "151199")]
pub fn saturating_duration_since(&self, earlier: SystemTime) -> Duration {
self.duration_since(earlier).unwrap_or(Duration::ZERO)
}
}

#[stable(feature = "time2", since = "1.8.0")]
Expand Down
39 changes: 39 additions & 0 deletions library/std/tests/time.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![feature(duration_constants)]
#![feature(time_systemtime_limits)]
#![feature(time_saturating_systemtime)]

use std::fmt::Debug;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
Expand Down Expand Up @@ -269,3 +270,41 @@ fn system_time_max_min() {
assert!(SystemTime::MIN.checked_add(MIN_INTERVAL).is_some());
assert!(SystemTime::MIN.checked_sub(MIN_INTERVAL).is_none());
}

#[test]
fn system_time_saturating() {
// Perform saturating addition on SystemTime::MAX to see how it behaves.
assert_eq!(SystemTime::MAX.saturating_add(Duration::ZERO), SystemTime::MAX);
assert_eq!(SystemTime::MAX.saturating_add(Duration::new(1, 0)), SystemTime::MAX);
assert!(SystemTime::MAX.checked_add(Duration::new(1, 0)).is_none());
assert_eq!(
SystemTime::MAX.saturating_sub(Duration::new(1, 0)),
SystemTime::MAX.checked_sub(Duration::new(1, 0)).unwrap()
);

// Perform saturating subtraction on SystemTime::MIn to see how it behaves.
assert_eq!(SystemTime::MIN.saturating_sub(Duration::ZERO), SystemTime::MIN);
assert_eq!(SystemTime::MIN.saturating_sub(Duration::new(1, 0)), SystemTime::MIN);
assert!(SystemTime::MIN.checked_sub(Duration::new(1, 0)).is_none());
assert_eq!(
SystemTime::MIN.saturating_add(Duration::new(1, 0)),
SystemTime::MIN.checked_add(Duration::new(1, 0)).unwrap()
);

// Check saturating_duration_since with various constant values.
assert!(SystemTime::MAX.saturating_duration_since(SystemTime::MIN) >= Duration::ZERO);
assert_eq!(SystemTime::MAX.saturating_duration_since(SystemTime::MAX), Duration::ZERO);
assert!(SystemTime::MAX.duration_since(SystemTime::MAX).is_ok());
assert_eq!(SystemTime::MIN.saturating_duration_since(SystemTime::MAX), Duration::ZERO);
assert!(SystemTime::MIN.duration_since(SystemTime::MAX).is_err());
assert_eq!(
(SystemTime::UNIX_EPOCH + Duration::new(1, 0))
.saturating_duration_since(SystemTime::UNIX_EPOCH),
Duration::new(1, 0)
);
assert_eq!(
SystemTime::UNIX_EPOCH
.saturating_duration_since(SystemTime::UNIX_EPOCH + Duration::new(1, 0)),
Duration::ZERO
);
}
Loading