BurntSushi / jiff

A date-time library for Rust that encourages you to jump into the pit of success.
The Unlicense
1.65k stars 26 forks source link

Consider adding comparison docs contrasting std types (Instant and SystemTime) #24

Open matklad opened 1 month ago

matklad commented 1 month ago

TL;DR: Adding a comparison section with std types which focuses on when not to use jiff would directly help prospective users of this to make informed decisions, and, indirectly, its a good opportunity to teach a lot of people about the intricate world of computer time.

Longer version:

Time is tricky. My understanding is that there are at least three different things that people colloquially refer to as time:

  1. Time as on the stopwatch, a span between two time measurements made with the same device, represented by std::time::Instant
  2. Time in the absolute sense, a specific unique moment in the life of the universe, represented by SystemTime (*)
  3. Absolute time at a particular geographic and administrative region of the earth: time + place + bureaucracy. This is the domain of the present library.

As you move down list, the number of things that could go wrong increases:

  1. Is pretty much infallible, if your language's runtime patches the underlying APIs to be monotonic.
  2. Introduces a nasty failure mode: time abruptly jump back and forth when the system synchronizes its clock.
  3. Further requires to keep up to date with the latest legislation of what are the timezones. In my lifetime, Russian government flip-flopped a couple times on the question of whether Russia has DST.

Generally, for robust software you want to stand on the lowest rung of this ladder possible to both:

The pedagogical issue here is this all is a pile of accidental complexity. So, unless you are already a domain expert, the way you think about this is "my software needs to track time", and you and up using the rung of the ladder which is the most available, without even realizing that there's a whole ladder.

I have observed chrono being used in places where something like std::time::SystemTime would make more sense.


This crate seems like an excellent opportunity to document all these, in order:

And a section comparing jiff with std::time might be a good form to surface this.

(*): I am of a mixed feelings about SystemTime. In theory, a type like this could take on two roles:

Rust SystemTime intentionally doesn't do the second part. Eg, to get a UNIX timestamp you have to do time::SystemTime::duration_since(time::UNIX_EPOCH).unwrap() which is quiet inconvenient. In the effect, all the actual algebraic API gets punted onto Duration.

Another thing that absolute time as POD should, but SystemTime doesn't, is formatting to/from UTC. As far as I understand, UTC and unix time are defined in such a way that interconverting between the two is a pure function that doesn't need tzinfo. This covers a significant use-case where you are writing software that needs to deal with absolute times, but also wants to show some human-readable representation of time. UTC is this representation.

So perhaps it is worth pulling jiff just for its Timestamp type?

BurntSushi commented 1 month ago

I think this is a great idea. I think the landscape is perhaps more complicated than you paint it, and is perhaps less linear. Some big missing components from your overview are Span and civil datetime. But overall, I think an approximate linear progress is not a bad way of tackling the concept of "absolute" time.

So perhaps it is worth pulling jiff just for its Timestamp type?

This could perhaps be made more tolerable by supporting this better with crate features. That is, letting one turn off time zone support (including the Zoned type) completely. I think some parts of the crate will need to be refactored to unglue some things, but it should be doable.

The Timestamp type does provide some other niceties like parsing and doing operations with a Span.

Another thing that absolute time as POD should, but SystemTime doesn't, is formatting to/from UTC. As far as I understand, UTC and unix time are defined in such a way that interconverting between the two is a pure function that doesn't need tzinfo.

Yes'ish, with the important caveat that not all UTC datetimes can be unambiguously represented as a Unix timestamp. (Because of leap seconds.) UTC is a tuple of (year, month, day, hour, minute, second) and that second value can sometimes be 60. But, for example, both (2015, 6, 30, 23, 59, 59) and (2015, 6, 30, 23, 59, 60) map to the same Unix timestamp.

(This is just a small clarification. It doesn't matter for the purposes of Jiff because Jiff ignores leap seconds.)