Should std::time::Instant implement Display?

Should std::time::Instant and std::time::SystemTime implement Display?

Currently they do not, and I was surprised that there wasn't a clear way to get a human readable timestamp out of them. Was this a deliberate choice, or just something that hasn't been done?

Instant by itself is rather abstract. The meaningful thing to print is the .elapsed() duration. Duration could possibly have a Display impl.

SystemTime is a can of worms, since there are countless locale-specific ways to print a datetime. It could perhaps print some dry ISO-8601 format, but that wouldn't be particularly user-friendly. Also SystemTime currently has very vague API that avoids exposing timezones. You can't print an absolute time without touching that nightmare.

11 Likes

I suspect this was deliberate, because human readable representation of time is a huge topic that doesn't belong to std ‒ it shouldn't take favorites and pick eg. US way to print them. If you want to communicate with the user with time, you probably want chrono or humantime or something to that direction anyway.

Note that all these have sensible Debug representation when you just need to put it to logs.

6 Likes

The formatting of datetimes is, to say the least, extremely subjective. There are an enormous number of ways to format a datetime, and it even changes with location (not just order of components, but punctuation and capitalization as well). When the format description is left to the user, there are still a number of ways to describe it: the time and chrono crates vary, and Unicode has its own specification (albeit somewhat limited).

Imo this should be left up to libraries. It certainly isn't trivial to implement there, either.

2 Likes

For Instant, it makes sense to me that it is too abstract to have a Display impl, though I've often wished for a more human-friendly serialization for Duration.

For SystemTime, I don't find the "number of ways to format" angle very persuasive, on the face of it an ISO 8601 or RFC 3339 representation seems like it would seem like a good improvement (including just an offset-based timezone). I do understand that the implementation side of it might be tricky, taking into account things like leap seconds.

3 Likes

I hope that if such a display representation is created, related impls are also defined for International Atomic Time (TAI) and Global Positioning System (GPS) time, neither of which suffer from unpredictable leap-seconds.

Given the large number of ways of formatting time to be human readable, I suspect that implementing Display on anything time-like is going to be a non-starter. Even if we develop some mechanism to format time within the standard library, unless it can be extended by user code it will be problematic. For example, some ancient time keeping systems used to split the day and night such that the day always had 12 hours and the night always had 12 hours... even as the seasons changed and the length of the day/night changed. While I don't think we'd want to use that today, I also don't want to prevent others from implementing it they wish to.

My suggestion is that if we really want to do something about this, we define new traits for the standard library similar to the following:

use std::fmt::Display;
use std::time::Duration;
use std::error::Error;

pub trait DisplayDuration: Display {
    /// Sets the `Duration` that will be formatted.
    fn set_duration(&mut self, duration: &Duration) -> Result<(), Box<dyn Error>>;
}

and similarly for the other time types.

We provide some simple implementations of the trait that might have some knobs to adjust the format in quasi-standard ways (e.g., an object that emulates strftime()), but end users are free to implement objects that are able to do more esoteric formatting, like for that ancient calendar I mentioned above.

As a side note, my google-fu is weak today; I can't find the name of the particular time system I mentioned earlier. Does anyone know what it is so I can edit this post later on?

This is the only thing I would expect to be in std as well. Just YYYY-MM-DDTHH:MM:SSZ; nothing else.

But thinking more, if that was going to be exposed for Display I'd also expect it to be exposed as a struct to get at those components (otherwise people will parse them out of the .to_string()) which would then imply a way to convert that back and forth to SystemTime, at which point we're back in the whole mess again.

So leaving this to an external crate sounds like the correct option.


I suppose Duration could have a Display using ISO 8601 durations like PT1M5S. Though it can't really support things like P1D properly, so even that is non-great because with a Display people would probably expect a FromStr...

4 Likes

Due to the presence of leap seconds, the only valid representation would be PT#S…which doesn't seem too useful.

The boundaries of application of Display trait are fuzzy. It's true that formatting a SystemTime is locale dependent, but so is, for example, formatting of an f32, so one could argue that f32 shouldn't implement Display, too. Display on bool is pretty questionable as well. Pretty much anything can be formatted in multiple different ways, and it's quite rare to have a type that has a single canonical representation. And Display is so vague that I'm having a hard time imagining code that is generic over Display in a useful way.

9 Likes

Oh, bleh. 3.1.1.8 -- despite talking about SI -- decides that a "clock minute" is different from an SI minute (PDF, page 33).

So those "durations" are really only about calendars. And of course they now say "time" (no longer "time point", per 8601-1:2019's forward) for something materially different from an SI "time" dimension.

:sob:

Exactly...there's a reason I typically refer to that as a "period", which requires a start/end point, rather than a "duration", which doesn't. It's a bit of a mess.

I think that using ISO 8601 durations could be viable. At least, there is prior art: Java Duration::toString does that. And it can parse it as well.

On the other hand, one could then assume that Instant could do the same… and I fully agree that this opens a can of worms that probably nobody wants to solve within std.

+1 for Z-normalized RFC3339.

Shameless plug for the tai64 crate: https://crates.io/crates/tai64

3 Likes

I agree. It's my opinion that refusing to implement Display because of arcane exceptionality is a rule that has been capriciously and inconsistently applied by std, to no one's benefit.

5 Likes

For many things there is a reasonable default way to format it. For time there are just way too many formats without any being used clearly more common than others.

1 Like