rust/library/std/src/time.rs
bors 1d71ba8623 Auto merge of #86191 - kawadakk:release-add-solid-support, r=nagisa,estebank,m-ou-se,
Add SOLID targets

This PR introduces new tier 3 targets for [SOLID](https://www.kmckk.co.jp/eng/SOLID/) embedded development platform by Kyoto Microcomputer Co., Ltd.

|          Target name           | `target_arch` | `target_vendor` | `target_os`  |
|--------------------------------|---------------|-----------------|--------------|
| `aarch64-kmc-solid_asp3`       | `aarch64`     | `kmc`           | `solid_asp3` |
| `armv7a-kmc-solid_asp3-eabi`   | `arm`         | `kmc`           | `solid_asp3` |
| `armv7a-kmc-solid_asp3-eabihf` | `arm`         | `kmc`           | `solid_asp3` |

## Related PRs

- [ ] `libc`: https://github.com/rust-lang/libc/pull/2227
- [ ] `cc`: https://github.com/alexcrichton/cc-rs/pull/609

## Non-blocking Issues

- [ ] The target kernel can support `Thread::unpark` directly, but this property is not utilized because the underlying kernel feature is used to implement `Condvar` and it's unclear whether `std` should guarantee that parking tokens are not clobbered by other synchronization primitives.
- [ ] The rustc book: The page title "\*-kmc-solid-\*" shows up as "-kmc-solid-" in TOC

## Tier 3 Target Policy

As tier 3 targets, the new targets are required to adhere to [the tier 3 target policy](https://doc.rust-lang.org/nightly/rustc/target-tier-policy.html#tier-3-target-policy) requirements. This section quotes each requirement in entirety and describes how they are met.

> - A tier 3 target must have a designated developer or developers (the "target maintainers") on record to be CCed when issues arise regarding the target. (The mechanism to track and CC such developers may evolve over time.)

See [`src/doc/rustc/src/platform-support/kmc-solid.md`](https://github.com/kawadakk/rust/blob/release-add-solid-support/src/doc/rustc/src/platform-support/kmc-solid.md).

> - Targets must use naming consistent with any existing targets; for instance, a target for the same CPU or OS as an existing Rust target should use the same name for that CPU or OS. Targets should normally use the same names and naming conventions as used elsewhere in the broader ecosystem beyond Rust (such as in other toolchains), unless they have a very good reason to diverge. Changing the name of a target can be highly disruptive, especially once the target reaches a higher tier, so getting the name right is important even for a tier 3 target.
>     - Target names should not introduce undue confusion or ambiguity unless absolutely necessary to maintain ecosystem compatibility. For example, if the name of the target makes people extremely likely to form incorrect beliefs about what it targets, the name should be changed or augmented to disambiguate it.

The new target names follow this format: `$ARCH-$VENDOR-$OS-$ABI`, which is already adopted by most existing targets. `$ARCH` and `$ABI` follow the convention: `aarch64-*` for AArch64, `armv7a-*-eabi` for Armv7-A with EABI. `$OS` is used to distinguish multiple variations of the platform in a somewhat similar way to the Apple targets, though we are only adding one variation in this PR. `$VENDOR` denotes the platform vendor name similarly to the Apple, Solaris, SGX, and VxWorks targets.

`$OS` corresponds to the value of `target_os` and takes the format `solid-$KERNEL`. The inclusion of a hyphen prevents unique decomposition of target names, though the mapping between target names and target attributes isn't trivial in the first place, e.g., because of the Android targets.

More targets may be added later, as we support other base kernels (there are at least three at the point of writing) and are interested in supporting other processor architectures in the future.

> - Tier 3 targets may have unusual requirements to build or use, but must not create legal issues or impose onerous legal terms for the Rust project or for Rust developers or users.
>     - The target must not introduce license incompatibilities.
>     - Anything added to the Rust repository must be under the standard Rust license (`MIT OR Apache-2.0`).
>     - The target must not cause the Rust tools or libraries built for any other host (even when supporting cross-compilation to the target) to depend on any new dependency less permissive than the Rust licensing policy. This applies whether the dependency is a Rust crate that would require adding new license exceptions (as specified by the `tidy` tool in the rust-lang/rust repository), or whether the dependency is a native library or binary. In other words, the introduction of the target must not cause a user installing or running a version of Rust or the Rust tools to be subject to any new license requirements.
>     - If the target supports building host tools (such as `rustc` or `cargo`), those host tools must not depend on proprietary (non-FOSS) libraries, other than ordinary runtime libraries supplied by the platform and commonly used by other binaries built for the target. For instance, `rustc` built for the target may depend on a common proprietary C runtime library or console output library, but must not depend on a proprietary code generation library or code optimization library. Rust's license permits such combinations, but the Rust project has no interest in maintaining such combinations within the scope of Rust itself, even at tier 3.
>     - Targets should not require proprietary (non-FOSS) components to link a functional binary or library.
>     - "onerous" here is an intentionally subjective term. At a minimum, "onerous" legal/licensing terms include but are *not* limited to: non-disclosure requirements, non-compete requirements, contributor license agreements (CLAs) or equivalent, "non-commercial"/"research-only"/etc terms, requirements conditional on the employer or employment of any particular Rust developers, revocable terms, any requirements that create liability for the Rust project or its developers or users, or any requirements that adversely affect the livelihood or prospects of the Rust project or its developers or users.

We intend to make the contribution fully available under the standard Rust license with no additional legal restrictions whatsoever. This PR does not introduce any new dependency less permissive than the Rust license policy, and we are willing to ensure this doesn't happen for future contributions regarding the new targets.

The new targets don't support building host tools.

Although the new targets use a platform-provided C compiler toolchain, it can be substituted by [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) for testing purposes.

> - Tier 3 targets should attempt to implement as much of the standard libraries as possible and appropriate (`core` for most targets, `alloc` for targets that can support dynamic memory allocation, `std` for targets with an operating system or equivalent layer of system-provided functionality), but may leave some code unimplemented (either unavailable or stubbed out as appropriate), whether because the target makes it impossible to implement or challenging to implement. The authors of pull requests are not obligated to avoid calling any portions of the standard library on the basis of a tier 3 target not implementing those portions.

Most features are implemented. The following features are not implemented due to the lack of native support:

- `fs::File::{file_attr, truncate, duplicate, set_permissions}`
- `fs::{symlink, link, canonicalize}`
- Process creation
- Command-line arguments

~~Networking is not implemented yet, and we intend to add it as soon as it's ready.~~
Edit (2021-07-07): Networking is now implemented.

Backtrace generation is not really a good fit for embedded targets, so it's intentionally left unimplemented. Unwinding is functional, however.

> - The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target supports running tests (even if they do not pass), the documentation must explain how to run tests for the target, using emulation if possible or dedicated hardware if necessary.

See [`src/doc/rustc/src/platform-support/kmc-solid.md`](https://github.com/kawadakk/rust/blob/release-add-solid-support/src/doc/rustc/src/platform-support/kmc-solid.md). Running tests is not supported.

> - Neither this policy nor any decisions made regarding targets shall create any binding agreement or estoppel by any party. If any member of an approving Rust team serves as one of the maintainers of a target, or has any legal or employment requirement (explicit or implicit) that might affect their decisions regarding a target, they must recuse themselves from any approval decisions regarding the target's tier status, though they may otherwise participate in discussions.
>     - This requirement does not prevent part or all of this policy from being cited in an explicit contract or work agreement (e.g. to implement or maintain support for a target). This requirement exists to ensure that a developer or team responsible for reviewing and approving a target does not face any legal threats or obligations that would prevent them from freely exercising their judgment in such approval, even if such judgment involves subjective matters or goes beyond the letter of these requirements.
> - Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a block on the PR based on a tier 3 target. Do not send automated messages or notifications (via any medium, including via ``@`)` to a PR author or others involved with a PR regarding a tier 3 target, unless they have opted into such messages.
>     - Backlinks such as those generated by the issue/PR tracker when linking to an issue or PR are not considered a violation of this policy, within reason. However, such messages (even on a separate repository) must not generate notifications to anyone involved with a PR who has not requested such notifications.
> - Patches adding or updating tier 3 targets must not break any existing tier 2 or tier 1 target, and must not knowingly break another tier 3 target without approval of either the compiler team or the maintainers of the other tier 3 target.
>     - In particular, this may come up when working on closely related targets, such as variations of the same architecture with different features. Avoid introducing unconditional uses of features that another variation of the target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target.

We acknowledge these requirements and intend to ensure they are met.

There are no closely related targets at the moment.
2021-09-28 11:50:33 +00:00

659 lines
25 KiB
Rust

//! Temporal quantification.
//!
//! # Examples:
//!
//! There are multiple ways to create a new [`Duration`]:
//!
//! ```
//! # use std::time::Duration;
//! let five_seconds = Duration::from_secs(5);
//! assert_eq!(five_seconds, Duration::from_millis(5_000));
//! assert_eq!(five_seconds, Duration::from_micros(5_000_000));
//! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
//!
//! let ten_seconds = Duration::from_secs(10);
//! let seven_nanos = Duration::from_nanos(7);
//! let total = ten_seconds + seven_nanos;
//! assert_eq!(total, Duration::new(10, 7));
//! ```
//!
//! Using [`Instant`] to calculate how long a function took to run:
//!
//! ```ignore (incomplete)
//! let now = Instant::now();
//!
//! // Calling a slow function, it may take a while
//! slow_function();
//!
//! let elapsed_time = now.elapsed();
//! println!("Running slow_function() took {} seconds.", elapsed_time.as_secs());
//! ```
#![stable(feature = "time", since = "1.3.0")]
mod monotonic;
#[cfg(test)]
mod tests;
use crate::error::Error;
use crate::fmt;
use crate::ops::{Add, AddAssign, Sub, SubAssign};
use crate::sys::time;
use crate::sys_common::FromInner;
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
#[unstable(feature = "duration_checked_float", issue = "83400")]
pub use core::time::FromSecsError;
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with [`Duration`].
///
/// Instants are always guaranteed to be no less 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 might 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).
///
/// The size of an `Instant` struct may vary depending on the target operating
/// system.
///
/// 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());
/// }
/// ```
///
/// # OS-specific behaviors
///
/// An `Instant` is a wrapper around system-specific types and it may behave
/// differently depending on the underlying operating system. For example,
/// the following snippet is fine on Linux but panics on macOS:
///
/// ```no_run
/// use std::time::{Instant, Duration};
///
/// let now = Instant::now();
/// let max_nanoseconds = u64::MAX / 1_000_000_000;
/// let duration = Duration::new(max_nanoseconds, 0);
/// println!("{:?}", now + duration);
/// ```
///
/// # Underlying System calls
/// Currently, the following system calls are being used to get the current time using `now()`:
///
/// | Platform | System call |
/// |-----------|----------------------------------------------------------------------|
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
/// | UNIX | [clock_gettime (Monotonic Clock)] |
/// | Darwin | [mach_absolute_time] |
/// | VXWorks | [clock_gettime (Monotonic Clock)] |
/// | SOLID | `get_tim` |
/// | WASI | [__wasi_clock_time_get (Monotonic Clock)] |
/// | Windows | [QueryPerformanceCounter] |
///
/// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get
/// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
///
/// **Disclaimer:** These system calls might change over time.
///
/// > Note: mathematical operations like [`add`] may panic if the underlying
/// > structure cannot represent the new point in time.
///
/// [`add`]: Instant::add
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[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.
///
/// The size of a `SystemTime` struct may vary depending on the target operating
/// system.
///
/// 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 occurred!
/// println!("Error: {:?}", e);
/// }
/// }
/// }
/// ```
///
/// # Underlying System calls
/// Currently, the following system calls are being used to get the current time using `now()`:
///
/// | Platform | System call |
/// |-----------|----------------------------------------------------------------------|
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
/// | UNIX | [clock_gettime (Realtime Clock)] |
/// | Darwin | [gettimeofday] |
/// | VXWorks | [clock_gettime (Realtime Clock)] |
/// | SOLID | `SOLID_RTC_ReadTime` |
/// | WASI | [__wasi_clock_time_get (Realtime Clock)] |
/// | Windows | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime] |
///
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html
/// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime
/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get
/// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
///
/// **Disclaimer:** These system calls might change over time.
///
/// > Note: mathematical operations like [`add`] may panic if the underlying
/// > structure cannot represent the new point in time.
///
/// [`add`]: SystemTime::add
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[stable(feature = "time2", since = "1.8.0")]
pub struct SystemTime(time::SystemTime);
/// An error returned from the `duration_since` and `elapsed` methods on
/// `SystemTime`, used to learn how far in the opposite direction a system time
/// lies.
///
/// # Examples
///
/// ```no_run
/// use std::thread::sleep;
/// use std::time::{Duration, SystemTime};
///
/// let sys_time = SystemTime::now();
/// sleep(Duration::from_secs(1));
/// let new_sys_time = SystemTime::now();
/// match sys_time.duration_since(new_sys_time) {
/// Ok(_) => {}
/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
/// }
/// ```
#[derive(Clone, Debug)]
#[stable(feature = "time2", since = "1.8.0")]
pub struct SystemTimeError(Duration);
impl Instant {
/// Returns an instant corresponding to "now".
///
/// # Examples
///
/// ```
/// use std::time::Instant;
///
/// let now = Instant::now();
/// ```
#[stable(feature = "time2", since = "1.8.0")]
pub fn now() -> Instant {
let os_now = time::Instant::now();
// And here we come upon a sad state of affairs. The whole point of
// `Instant` is that it's monotonically increasing. We've found in the
// wild, however, that it's not actually monotonically increasing for
// one reason or another. These appear to be OS and hardware level bugs,
// and there's not really a whole lot we can do about them. Here's a
// taste of what we've found:
//
// * #48514 - OpenBSD, x86_64
// * #49281 - linux arm64 and s390x
// * #51648 - windows, x86
// * #56560 - windows, x86_64, AWS
// * #56612 - windows, x86, vm (?)
// * #56940 - linux, arm64
// * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar
// Firefox bug
//
// It seems that this just happens a lot in the wild.
// We're seeing panics across various platforms where consecutive calls
// to `Instant::now`, such as via the `elapsed` function, are panicking
// as they're going backwards. Placed here is a last-ditch effort to try
// to fix things up. We keep a global "latest now" instance which is
// returned instead of what the OS says if the OS goes backwards.
//
// To hopefully mitigate the impact of this, a few platforms are
// excluded as "these at least haven't gone backwards yet".
if time::Instant::actually_monotonic() {
return Instant(os_now);
}
Instant(monotonic::monotonize(os_now))
}
/// Returns the amount of time elapsed from another instant to this one.
///
/// # Panics
///
/// This function will panic if `earlier` is later than `self`.
///
/// # Examples
///
/// ```no_run
/// use std::time::{Duration, Instant};
/// use std::thread::sleep;
///
/// let now = Instant::now();
/// sleep(Duration::new(1, 0));
/// let new_now = Instant::now();
/// println!("{:?}", new_now.duration_since(now));
/// ```
#[stable(feature = "time2", since = "1.8.0")]
pub fn duration_since(&self, earlier: Instant) -> Duration {
self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self")
}
/// Returns the amount of time elapsed from another instant to this one,
/// or None if that instant is later than this one.
///
/// # Examples
///
/// ```no_run
/// use std::time::{Duration, Instant};
/// use std::thread::sleep;
///
/// let now = Instant::now();
/// sleep(Duration::new(1, 0));
/// let new_now = Instant::now();
/// println!("{:?}", new_now.checked_duration_since(now));
/// println!("{:?}", now.checked_duration_since(new_now)); // None
/// ```
#[stable(feature = "checked_duration_since", since = "1.39.0")]
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
self.0.checked_sub_instant(&earlier.0)
}
/// Returns the amount of time elapsed from another instant to this one,
/// or zero duration if that instant is later than this one.
///
/// # Examples
///
/// ```no_run
/// use std::time::{Duration, Instant};
/// use std::thread::sleep;
///
/// let now = Instant::now();
/// sleep(Duration::new(1, 0));
/// let new_now = Instant::now();
/// println!("{:?}", new_now.saturating_duration_since(now));
/// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
/// ```
#[stable(feature = "checked_duration_since", since = "1.39.0")]
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
}
/// 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
}
/// 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.
#[stable(feature = "time_checked_add", since = "1.34.0")]
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
self.0.checked_add_duration(&duration).map(Instant)
}
/// 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.
#[stable(feature = "time_checked_add", since = "1.34.0")]
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
self.0.checked_sub_duration(&duration).map(Instant)
}
}
#[stable(feature = "time2", since = "1.8.0")]
impl Add<Duration> for Instant {
type Output = Instant;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Instant {
self.checked_add(other).expect("overflow when adding duration to instant")
}
}
#[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 {
self.checked_sub(other).expect("overflow when subtracting duration from instant")
}
}
#[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 {
/// 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.
///
/// # Examples
///
/// ```no_run
/// use std::time::SystemTime;
///
/// match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
/// Err(_) => panic!("SystemTime before UNIX EPOCH!"),
/// }
/// ```
#[stable(feature = "assoc_unix_epoch", since = "1.28.0")]
pub const UNIX_EPOCH: SystemTime = UNIX_EPOCH;
/// Returns the system time corresponding to "now".
///
/// # Examples
///
/// ```
/// use std::time::SystemTime;
///
/// let sys_time = SystemTime::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).
/// [`Instant`] can be used to measure elapsed time without this risk of failure.
///
/// If successful, <code>[Ok]\([Duration])</code> 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.
///
/// # Examples
///
/// ```no_run
/// use std::time::SystemTime;
///
/// let sys_time = SystemTime::now();
/// let new_sys_time = SystemTime::now();
/// let difference = new_sys_time.duration_since(sys_time)
/// .expect("Clock may have gone backwards");
/// println!("{:?}", difference);
/// ```
#[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 difference between the clock time when this
/// system time was created, and the current clock time.
///
/// 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 might not always succeed. If successful, <code>[Ok]\([Duration])</code> is
/// returned where the duration represents the amount of time elapsed from
/// this time measurement to the current time.
///
/// To measure elapsed time reliably, use [`Instant`] instead.
///
/// 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.
///
/// # Examples
///
/// ```no_run
/// use std::thread::sleep;
/// use std::time::{Duration, SystemTime};
///
/// let sys_time = SystemTime::now();
/// let one_sec = Duration::from_secs(1);
/// sleep(one_sec);
/// assert!(sys_time.elapsed().unwrap() >= one_sec);
/// ```
#[stable(feature = "time2", since = "1.8.0")]
pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
SystemTime::now().duration_since(*self)
}
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
#[stable(feature = "time_checked_add", since = "1.34.0")]
pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
self.0.checked_add_duration(&duration).map(SystemTime)
}
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
#[stable(feature = "time_checked_add", since = "1.34.0")]
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
self.0.checked_sub_duration(&duration).map(SystemTime)
}
}
#[stable(feature = "time2", since = "1.8.0")]
impl Add<Duration> for SystemTime {
type Output = SystemTime;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`SystemTime::checked_add`] for a version without panic.
fn add(self, dur: Duration) -> SystemTime {
self.checked_add(dur).expect("overflow when adding duration to instant")
}
}
#[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 {
self.checked_sub(dur).expect("overflow when subtracting duration from instant")
}
}
#[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.
///
/// # Examples
///
/// ```no_run
/// use std::time::{SystemTime, UNIX_EPOCH};
///
/// match SystemTime::now().duration_since(UNIX_EPOCH) {
/// Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
/// Err(_) => panic!("SystemTime before UNIX EPOCH!"),
/// }
/// ```
#[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 [`SystemTime::duration_since`]
/// and [`SystemTime::elapsed`] methods whenever the second system time
/// represents a point later in time than the `self` of the method call.
///
/// # Examples
///
/// ```no_run
/// use std::thread::sleep;
/// use std::time::{Duration, SystemTime};
///
/// let sys_time = SystemTime::now();
/// sleep(Duration::from_secs(1));
/// let new_sys_time = SystemTime::now();
/// match sys_time.duration_since(new_sys_time) {
/// Ok(_) => {}
/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
/// }
/// ```
#[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 {
#[allow(deprecated)]
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)
}
}