Move parts of `SystemTime` into core?

There was a previous discussion about this:

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.

1 Like

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.

1 Like

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.

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 Durations.

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

2 Likes

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.

1 Like

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.

3 Likes

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.

As I said:

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?

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.

1 Like

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?

I'll just say something about my motivation:

I've been working on gloo::file, 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 panics. But it instinctively feels like I should be using stuff from core because it would be more correct.

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 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.

2 Likes

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.

1 Like

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.

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.

2 Likes

...doesn't an OS typically return file modification time in milliseconds since epoch? posix, windows

1 Like

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.)

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.

1 Like

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?

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. That's probably not the greatest reason to put SystemTime in core, but without it fixed chrono + no_std is pretty painful.

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.

3 Likes