# Move parts of \`SystemTime\` into core?

**URL:** <https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844>\
**Category:** libs\
**Created:** [February 17, 2020, 2:40pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844 "2020-02-17T14:40:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 17, 2020, 2:40pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/1 "2020-02-17T14:40:00Z")

</div>

There was a previous discussion about this:

> [@Pre-RFC: Move SystemTime and Duration to libcore](https://internals.rust-lang.org/t/pre-rfc-move-systemtime-and-duration-to-libcore/3903):
>
> 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…

I'm not sure I understand the rationale for not including `SystemTime` in libcore. Obviously the `now` and `elapsed` functions could not be implemented in `libcore`, but the only problem after that seems to be about the internal precision of the type.

But, the internals of the type are private anyway, and there isn't ABI compatibility between releases, so I don't see how this is a problem. Can anyone shed any light on this for me?

The motivation for including `SystemTime` in libcore is that it is a good base-level instant in time that can be returned from libs without tying to a particular time implementation e.g. [chrono](https://crates.io/crates/chrono).

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 17, 2020, 2:52pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/2 "2020-02-17T14:52:53Z")

</div>

From the thread it seems there are two dealbreakers:

- `SystemTime::now()` does need an OS, so it's unfit for `core`
- Range and precision of `SystemTime` needs to be large enough to losslessly represent timestamps returned by the OS, including times older than unix epoch.

This could get better if/when Rust moves away from separate core+std into std with features. Then it could define `SystemTime` with or without the `now()` method.

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 17, 2020, 4:23pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/3 "2020-02-17T16:23:04Z")

</div>

Is the problem that `SystemTime` has have the same `impl` blocks in core and std?

Also, is range and precision something that has to be guaranteed future-compatible? As an example of this not holding, firefox has reduced the precision of some timings to make it harder to fingerprint browsers.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 17, 2020, 10:49pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/4 "2020-02-17T22:49:09Z")

</div>

Let's say this _were_ placed into core, regardless of why. What purpose would it then serve? The only two ways to create a `SystemTime` (afaik) are `SystemTime::now()` and `SystemTime::UNIX_EPOCH`. The former can't exist without an OS. The latter _could_, but now we just have a convoluted way to add and subtract `Duration`s.

That's not to mention the underlying representation, which is an OS-level construct.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 18, 2020, 12:41am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/5 "2020-02-18T00:41:08Z")

</div>

> [@derekdreery](#):
>
> Also, is range and precision something that has to be guaranteed future-compatible? As an example of this not holding, firefox has reduced the precision of some timings to make it harder to fingerprint browsers.

Rust needs to provide sufficient precision to not truncate the precision of the underlying platform. How much precision the underlying platform provides isn't up to Rust.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 18, 2020, 1:05am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/6 "2020-02-18T01:05:07Z")

</div>

> [@jhpratt](#):
>
> Let's say this _were_ placed into core, regardless of why. What purpose would it then serve?

Crates that just need to _process_ `SystemTime` instances, but doesn't need to _create_ `SystemTime` instances, could build without std. For instance, crates that just need to declare trait instances for `SystemTime` could build without std.

Also, crates could create a `SystemTime` by adding a `Duration` to the EPOCH.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 18, 2020, 1:29am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/7 "2020-02-18T01:29:46Z")

</div>

> [@josh](#):
>
> Crates that just need to _process_ `SystemTime` instances, but doesn't need to _create_ `SystemTime` instances, could build without std. For instance, crates that just need to declare trait instances for `SystemTime` could build without std.

Sure, the crate could build without std, but that serves no purpose unless _someone_ is able to create a `SystemTime`.

All I can think of is someone having a crate that does operations on it that currently requires a "std" feature flag (there are plenty examples here). This would eliminate the need for it to be gated, while still allowing operations, depending on the internal representation, of course. I personally don't find that to be justification enough, but I suppose that can be debated.

> [@josh](#):
>
> Also, crates could create a `SystemTime` by adding a `Duration` to the EPOCH.

As I said:

> [@jhpratt](#):
>
> now we just have a convoluted way to add and subtract `Duration`s.

If you're going to construct a `SystemTime` from the Unix timestamp or similar, would it not make more sense at that point to have a struct with plenty of methods & inspection capabilities, rather than a mostly opaque object?

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 18, 2020, 3:16pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/8 "2020-02-18T15:16:46Z")

</div>

> [@josh](#):
>
> How much precision the underlying platform provides isn't up to Rust.

Isn't the "answer" here to do the C++ `std::chrono` thing and make everything generic over the underlying precision? Like, I don't think this is a great idea, but we should at least take the position that `std::chrono` is kinda nuts if we implictly already think it is.

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 18, 2020, 7:01pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/9 "2020-02-18T19:01:40Z")

</div>

> [@josh](#):
>
> Rust needs to provide sufficient precision to not truncate the precision of the underlying platform. How much precision the underlying platform provides isn't up to Rust.

So in the case where there isn't an underlying OS (for example wasm32-unknown-unknown), couldn't we just use the same precision as `Duration`?

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 18, 2020, 7:05pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/10 "2020-02-18T19:05:48Z")

</div>

I'll just say something about my motivation:

I've been working on [`gloo::file`](https://github.com/rustwasm/gloo/blob/master/crates/file/src/blob.rs#L242), where a file has a modification time. It seemed to me that the correct semantic type for the modified type was `std::time::SystemTime`. `Duration` has a couple of downsides

1. It cannot handle times before 1970-01-01 (these things are not an issue until the are, in practice)
2. What we are returning is not a duration, it is a point in time.

So for these reasons `SystemTime` seems to be most appropriate type. Now in the case of `wasm32-unknown-unknown`, `std` is implemented, with the OS stuff stubbed out with `panic`s. But it instinctively feels like I should be using stuff from `core` because it would be more correct.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 18, 2020, 7:43pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/11 "2020-02-18T19:43:50Z")

</div>

> [@derekdreery](#):
>
> where a file has a modification time

Are you sure this is a system time? This seems a lot like a "civil" time to me that would be better served by the [chrono](https://docs.rs/chrono/0.4.10/chrono/) crate instead. The distinction between an "instant in time" as understood by computers and a "point in time" (also called a date or a civil time) is a fairly subtle one.

---

<div class="post-metadata">

**Author:** ![anp](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/anp/32/6036_2.png) [@anp](https://internals.rust-lang.org/u/anp)\
**Post date:** [February 18, 2020, 8:37pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/12 "2020-02-18T20:37:46Z")

</div>

> What we are returning is not a duration, it is a point in time.

nit: most (all?) representations of a point in time are a duration with a zero-point.

I agree that in the case of wasm32-unknown-unknown it can be weird to reach for std, but the case you highlight is an interaction with filesystem APIs that `core` doesn't include. It would seem weirder to me to motivate OS-level types in `core` based on std-level operations.

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [February 20, 2020, 2:20pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/13 "2020-02-20T14:20:56Z")

</div>

> [@mcy](#):
>
> Are you sure this is a system time? This seems a lot like a "civil" time to me that would be better served by the [chrono](https://docs.rs/chrono/0.4.10/chrono/) crate instead

I don't want to force people to use the chrono crate, I'd rather use some underlying representation, then let people choose their date/time crate.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 20, 2020, 4:38pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/14 "2020-02-20T16:38:37Z")

</div>

The underlying representation for a civil time is the six-tuple of (year, month, day, hour, minute, second), which is _not_ canonically convertible to a timestamp (you must pick a timezone, and even then the conversion is sytem-dependent).

Maybe it's a failure on `std`'s part that it fails to provide a civil time type, but timezones are such a dumpster fire that I'm not sure it's something we want to be handling in the standard library.

If you don't want to force people into a particular civil time crate, you should abstract over civil times in some way, rather than trying to solve this XY problem.

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [February 20, 2020, 5:36pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/15 "2020-02-20T17:36:03Z")

</div>

> [@derekdreery](#):
>
> where a file has a modification time

> [@mcy](#):
>
> Are you sure this is a system time? This seems a lot like a "civil" time to me

...doesn't an OS typically return file modification time in milliseconds since epoch? [posix](https://linux.die.net/man/2/lstat), [windows](https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime)

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [February 20, 2020, 9:06pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/16 "2020-02-20T21:06:35Z")

</div>

Unclear. I'm mosty going off of "I want to do this no\_std", which precludes any source of a "time unit since epoch". I feel like morally such things aught to be civil times (maybe with a timezone attached), even if posix and windows disagree.

(I especially believe that posix is terrible prior art, and mostly an example of how not to do things. I will let a windows person harp on whether windows got it wrong.)

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 20, 2020, 10:27pm UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/17 "2020-02-20T22:27:33Z")

</div>

Whether you have a local time that needs a time zone attached, or a time from some reference point that might need converting _into_ a local time for display, depends on where you got the time from. I would generally expect a file modification time to be a reference time that would need converting into local time for display purposes, but only if you actually need to display it. If you're (for instance) comparing it to other file modification times, or using it as a git commit timestamp, you don't need to do any kind of conversion.

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [February 21, 2020, 12:34am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/18 "2020-02-21T00:34:38Z")

</div>

> [@mcy](#):
>
> morally such things aught to be civil times (maybe with a timezone attached), even if posix and windows disagree

Libraries wrap OS-es, File Systems, hardware devices. If those give/take millis since epoch, wouldn't you want a 1st layer of functions operating in them directly and a 2nd later operating in civil time?

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 21, 2020, 4:57am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/19 "2020-02-21T04:57:55Z")

</div>

> [@jhpratt](#):
>
> Let's say this _were_ placed into core, regardless of why. What purpose would it then serve?

My use case for this would be getting the time from an SRTC and using it with e.g. credential libraries which check a credential is still valid given the current time. Ideally I'd like to also work with libraries which obtain the current time (via NTP and/or Roughtime) and use it to update/sync the SRTC to external time sources.

Sidebar: I have attempted to use `chrono` + `no_std`, but found it problematic for a few different reasons, most notably [a Cargo bug which activates the `std` feature in `chrono` if any of your build dependencies use `chrono` with the `std` feature activated](https://github.com/rust-lang/cargo/issues/4866). That's probably not the greatest reason to put `SystemTime` in `core`, but without it fixed `chrono` + `no_std` is pretty painful.

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [February 21, 2020, 5:35am UTC](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844/20 "2020-02-21T05:35:56Z")

</div>

> [@mcy](#):
>
> morally such things aught to be civil times (maybe with a timezone attached)

I disagree. Civil time is discontinuous, with leap seconds and with winter-time/summer-time hour shifts (albeit with a timezone change when someone remembers to include the time zone in the time representation). Well-intentioned people have tried to mix civil time into control-system algorithms like PID (proportional-integral-derivative) for years, without considering what happens when the civil time stutters on a leap second or the derivative reverses sign. One need only review control-system history records over leap-second stutters or during the hour skip-advance or skip-back-repeat at the onset of winter or summer time to see the confusion caused by redundant or skipped time-stamps.

[Next page](https://internals.rust-lang.org/t/move-parts-of-systemtime-into-core/11844.md?page=2)
