# Pre-RFC: Move SystemTime and Duration to libcore

**URL:** <https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903>\
**Category:** libs\
**Created:** [August 22, 2016, 6:25am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903 "2016-08-22T06:25:18Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 6:25am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/1 "2016-08-22T06:25:18Z")

</div>

## Proposal

- Move [`std::time::Duration`](https://doc.rust-lang.org/std/time/struct.Duration.html) to `core::time::Duration` and re-export it as `std::time::Duration`.
- Move [`std::time::SystemTime`](https://doc.rust-lang.org/std/time/struct.SystemTime.html) to `core::time::SystemTime` and re-export it as `std::time::SystemTime`.
- Move [`std::time::UNIX_EPOCH`](https://doc.rust-lang.org/std/time/constant.UNIX_EPOCH.html) to `core::time::UNIX_EPOCH` and re-export it as `std::time::UNIX_EPOCH`.
- Deprecate [`std::time::SystemTime::now()`](https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.now), replacing it with a standalone `std::time::now()` function.
- Deprecate [`std::time::SystemTime::elapsed()`](https://doc.rust-lang.org/std/time/struct.SystemTime.html#method.elapsed). Users would be encouraged to use `std::time::now().duration_since(x)`.

In the future, we might move `std::time::Instant` to libcore. This is out of the scope of this proposal.

In the future, we might provide some pluggable interface so that an application and/or platform port can provide its own implementation of the `std::time::now()`. This is out of the scope of this proposal.

This proposal is not adding any new functionality; it is just exposing some more functionality from libcore that’s already exposed from libstd.

### Motivation

Some crates want to be able to compare times without depending on libstd, so that they can work with the `#[no_std]` feature. Exposing the functionality for comparing times from libcore is helpful for this. Concrete examples include my [webpki](https://github.com/briansmith/webpki) crate and some other crates I am developing. I believe this would eventually be useful for [rustls](https://github.com/ctz/rustls) and many other crates. Rust operating systems might even be able to use these types as their native time/duration types.

libcore/libstd doesn’t necessarily know how to get the current time (in UTC) on every platform, and libstd might not be available. But, the application may have a way of getting the current system time (in UTC), in which case it can construct a `SystemTime` itself. (Consider, for example, a network of IoT devices where only one trusted device knows what time it is, and other devices on the network fetch the time from it.) Or, the application may not need to do time comparisons based on the current time, but rather only on two explicitly-given times, in which case `now()` and `elapsed()` are not needed. This is why they would stay libstd-only. For now, it is expected that `#![no_std]` applications would construct a `SystemTime` by adding some `Duration` to `UNIX_EPOCH`, where the `Duration` is constructed by some non-libcore/libstd API that returns the current time as an integer (milliseconds or whatever) relative to the (or some) epoch.

This subset of the API is a good fit for libcore because it is self-contained. In particular, it doesn’t depend on the memory allocator or other things that aren’t normally present in libcore. Since the code is platform-independent, this proposal doesn’t make it harder to port libcore. Applications that don’t use this functionality won’t be (negatively) affected by it.

### Drawbacks

libstd would still need to provide `std::time::SystemTime::now()` and `std::time::SystemTime::elapsed()` for backward compatibility, which means that exposing `std::time::SystemTime` wouldn’t be as simple as `pub use core::time::SystemTime`. However, I assume there’s already some mechanism for doing this that’s already considered acceptable for other uses.

### Alternatives

A crate that doesn’t want to depend on libstd could, in theory, use traits and/or other abstraction mechanisms to provide an API that accepts `std::time::SystemTime` _or_ some other kind of time. Then `#![no_std]` uses of the crate would use the trait. I experimented with doing this in one crate ([webpki](https://github.com/briansmith/webpki)), and it can be made to work, but it isn’t as clean as just having `SystemTime` always available.

### Thank you

Thank you for taking the time to review this proposal.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 22, 2016, 6:40am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/2 "2016-08-22T06:40:03Z")

</div>

> [@briansmith](#):
>
> But, the application may have a way of getting the current system time (in UTC), in which case it can construct a SystemTime itself.

Right now only `libstd` can construct a `SystemTime`, so for your idea to work, it would need to expose a public way of constructing `SystemTime`. The representation of `SystemTime` however, depends heavily on the platform's method of acquiring the current time, so you'd have an API in `libcore` that depends on system libraries even though `libcore` is supposed to be independent of that. What would the representation of `SystemTime` be on a platform where `libstd` doesn't know how to get the current time? What happens if `libcore` stabilizes on a specific representation for that platform and then `libstd` wants to use a different API with a different representation to get the time?

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 7:00am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/3 "2016-08-22T07:00:42Z")

</div>

> [@retep998](#):
>
> Right now only libstd can construct a SystemTime, so for your idea to work, it would need to expose a public way of constructing SystemTime.

There is already such a way: Add a `Duration` to `UNIX_EPOCH`.

> The representation of SystemTime however, depends heavily on the platform's method of acquiring the current time, so you'd have an API in libcore that depends on system libraries even though libcore is supposed to be independent of that. What would the representation of SystemTime be on a platform where libstd doesn't know how to get the current time? What happens if libcore stabilizes on a specific representation for that platform and then libstd wants to use a different API with a different representation to get the time?

It's pretty much always going to be a 64-bit integer offset from some epoch that would be a constant `Duration` away from `UNIX_EPOCH`, right?. Maybe the units would vary?

I actually did a very similar thing in mozilla::pkix; see [mozillapkix/lib/pkixtime.cpp at master · briansmith/mozillapkix · GitHub](https://github.com/briansmith/mozillapkix/blob/master/lib/pkixtime.cpp). There, we didn't need sub-second resolution, so it was a bit easier.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 22, 2016, 7:05am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/4 "2016-08-22T07:05:56Z")

</div>

> [@briansmith](#):
>
> It's pretty much always going to be a 64-bit integer offset from some epoch that would be a constant Duration away from UNIX\_EPOCH, right?. Maybe the units would vary?

[unix](https://github.com/rust-lang/rust/blob/3cc3ad11e6fadcba443cc50ba6ed03ab04d34355/src/libstd/sys/unix/time.rs#L124-L126) vs [windows](https://github.com/rust-lang/rust/blob/c66d2380a810c9a2b3dbb4f93a830b101ee49cc2/src/libstd/sys/windows/time.rs#L29-L31) The main difference between representations is the level of precision and the range of times that can be represented.

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 7:17am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/5 "2016-08-22T07:17:30Z")

</div>

> [@retep998](#):
>
> The main difference between representations is the level of precision and the range of times that can be represented.

AFAICT, there could be a single representation of `SystemTime` as a `Duration` (thus nanosecond solution) since the UNIX epoch, and we can say that times before the UNIX epoch are not necessarily supported. (I think this is kind of implied already.) Or we could even define `SystemTime` as a number of nanoseconds since the UNIX epoch.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 22, 2016, 7:22am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/6 "2016-08-22T07:22:21Z")

</div>

> [@briansmith](#):
>
> Or we could even define SystemTime as a number of nanoseconds since the UNIX epoch.

`SystemTime` necessarily depends on what sort of times the system can return. Windows can handle system times that are older than the UNIX epoch. What would libstd do if its `SystemTime` was simply nanoseconds since the UNIX epoch and it received such a time from Windows?

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 7:47am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/7 "2016-08-22T07:47:11Z")

</div>

> [@retep998](#):
>
> SystemTime necessarily depends on what sort of times the system can return. Windows can handle system times that are older than the UNIX epoch. What would libstd do if its SystemTime was simply nanoseconds since the UNIX epoch and it received such a time from Windows?

Maybe the same thing as when you're reading an NTFS filesystem on Linux and the last modified time of a file is earlier than the Unix epoch? A user of `SystemTime` can't expect times earlier than the Unix epoch to work. If a person needs the actual timestamp of a file, or whatever, that might be earlier than the Unix epoch then an operating-system-specific API should be used.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 22, 2016, 7:53am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/8 "2016-08-22T07:53:26Z")

</div>

> [@briansmith](#):
>
> Maybe the same thing as when you're reading an NTFS filesystem on Linux and the last modified time of a file is earlier than the Unix epoch?

In that case it is the operating system's problem, not Rust's problem.

> [@briansmith](#):
>
> If a person needs the actual timestamp of a file, or whatever, that might be earlier than the Unix epoch then an operating-system-specific API should be used.

`SystemTime` is that operating system specific API. It is supposed to be able to precisely represent any time that the OS returns so it can be given back to the OS without any loss of information. That is why it is called `SystemTime` and not `UnixTime`.

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 8:19am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/9 "2016-08-22T08:19:35Z")

</div>

I propose this:

In libcore, `SystemTime` only needs to be specified to be able to store the result of adding any `Duration` to `UNIX_EPOCH`; i.e. times with nanosecond resolution on or after 1970-01-01 and before whatever would cause a 64-bit overflow with nanosecond resolution. Thus, the default representation can indeed be a `Duration` relative to `UNIX_EPOCH`.

In libstd, in addition to handling any result of adding a `Duration` to `UNIX_EPOCH`, `SystemTime` also needs to be able to handle “any time the OS returns”. This might call for a specialized representation for libstd; the same specialized representation shoujld be used for libcore on that same platform.

---

<div class="post-metadata">

**Author:** ![retep998](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/retep998/32/729_2.png) [@retep998](https://internals.rust-lang.org/u/retep998)\
**Post date:** [August 22, 2016, 8:25am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/10 "2016-08-22T08:25:55Z")

</div>

> [@briansmith](#):
>
> whatever would cause a 64-bit overflow with nanosecond resolution

About 585 years after the epoch, which is why `Duration` is not simply 64-bit nanoseconds, but rather 64-bit seconds with a 32-bit nanosecond part.

---

<div class="post-metadata">

**Author:** ![seanmonstar](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/seanmonstar/32/36_2.png) [@seanmonstar](https://internals.rust-lang.org/u/seanmonstar)\
**Post date:** [August 22, 2016, 3:58pm UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/11 "2016-08-22T15:58:37Z")

</div>

> [@briansmith](#):
>
> Proposal: Sealed traits

I imagine the "Sealed traits" part is because of copying another pre-RFC?

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 22, 2016, 5:50pm UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/12 "2016-08-22T17:50:51Z")

</div>

> [@seanmonstar](#):
>
> I imagine the "Sealed traits" part is because of copying another pre-RFC?

Yes! I edited that out now.

---

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [August 23, 2016, 4:50am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/13 "2016-08-23T04:50:31Z")

</div>

I like the idea of the RFC (and am generally in favor of moving things into core), but I understand and sort of agree with the sentiment that _`System`_`Time` is platform-specific. I’d be more interested in seeing a generic Date/Time API that can work in core. There should be conversions between that and `SystemTime`.

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [August 26, 2016, 1:36am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/14 "2016-08-26T01:36:33Z")

</div>

> [@jethrogb](#):
>
> I like the idea of the RFC (and am generally in favor of moving things into core), but I understand and sort of agree with the sentiment that SystemTimeis platform-specific. I'd be more interested in seeing a generic Date/Time API that can work in core. There should be conversions between that andSystemTime.

There is one, `Instant`. However, it has the undesirable property of promising to be monotonically increasing, which requires it to be less efficient in various ways. And, it doesn't provide any functionality to ground it into a calendar.

We could define a third time type, to go along with `Instant` and `SystemTime`. But, IMO, it wouldn't improve the situation for any system where libstd already implements `SystemTime`, which is almost every platform. Adding a new type would be pure increased complexity for those platforms. My idea of generalizing `SystemTime` so it can work in libcore is to avoid adding any new complexity.

It is interesting that `Duration` has nanosecond resolution but `SystemTime` doesn't necessarily. I guess that means that laws of addition don't apply; e.g. this assertion may fail: `assert_eq!(s + d - s, d)`. If this is allowed, it may not be a good idea to use `Duration` as the internal storage of a generic `SystemTime` implementation, since it would be storing the nanoseconds component which is generally unnecessary.

In any case, if the libs team would rather have a seperate type like `UnixTime` then I can define this in my own crate, I think.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:26am UTC](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903/15 "2019-03-25T08:26:43Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
