BurntSushi / jiff

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

Consider treating weeks as uniform sometimes in the `Span` API #136

Open alilleybrinker opened 2 hours ago

alilleybrinker commented 2 hours ago

As I understand it from the docs, days are treated as uniform unless a zone-aware datetime is attached, but weeks are (for simplicity) always treated as non-uniform.

This has some implications for things like the Span::compare function, where a non-zero week value means the Span can't be compared without providing an attached zone-aware datetime.

However, in theory the same optionally-uniform behavior that exists for days could exist for weeks, where weeks are treated as being equivalent to 7 days (168 hours), and thus uniform, unless a zone-aware datetime is attached, in which case they are treated as non-uniform.

BurntSushi commented 2 hours ago

Yeah I've thought about this. The restriction comes from Temporal, which I think has a slightly different concern in play: they support more than Gregorian calendars. And so, I think, weeks aren't necessarily guaranteed to be uniform in that context. (Although I believe they are in practice for the calendars Temporal currently supports.) But Jiff is Gregorian-only and probably will remain so, with crates like icu filling in the gap for non-Gregorian use cases (I hope).

So with that said, it does seem like we could make weeks be treated as uniform. However, in #48, it's been brought up that treating days as uniform by default can be somewhat of a footgun in certain circumstances. To fix that, I'm likely going to make days non-uniform by default in all Span APIs. But to work around the hitch of providing a "dummy" date to get 24-hour days in cases where you want that, I plan to add a way to "mark" (opt-in) Span routines as a way to assume that all days are 24 hours long. So, for example, something like SpanRelativeTo::all_days_are_24_hours() or something of that nature. That could in turn also make weeks uniform as well.

Do you have a specific case you're running into where weeks not being uniform is giving you trouble?

alilleybrinker commented 2 hours ago

Thanks for the explanation!

The use case I have is for Hipcheck, where we have a small DSL we call "policy expressions" to which we are adding support for basic date and time operations, backed by jiff, with one of the two primitive types we're exposing being backed by jiff::Span. We'd like for users to be able to specify weeks and days and have them both treated as uniform (and thus comparable), and for the moment supporting that will mean doing some pre-processing to convert any user-provided weeks to days.

BurntSushi commented 2 hours ago

Ah yeah I see. Yeah I agree the pre-processing is the way to go for now.

Popping up a level, is there a way to get a meaningful relative date in the context of your DSL? It could be Zoned::now() for example, or some datetime extracted from something else (apologies for my fumbling here, I don't have a ton of context on how Hipcheck works). If you have that, then this problem would go away entirely and you'd be able to support spans with years and months too.

alilleybrinker commented 2 hours ago

We're definitely considering some ways to enrich Spans with datetime context. We'd like want to provide some way for the user to explicitly say when they want to do that, rather than inferring it, and we haven't decided how we'd like to do that yet.