Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an interval type, or modify Duration to allow larger spans #52

Closed
sgrif opened this issue Dec 2, 2015 · 7 comments
Closed

Add an interval type, or modify Duration to allow larger spans #52

sgrif opened this issue Dec 2, 2015 · 7 comments

Comments

@sgrif
Copy link

sgrif commented Dec 2, 2015

It would be great to have a data type which behaves similarly to the PostgreSQL interval data type. Unlike the duration type currently in Rust Chrono, it stores days and months as separate fields. Days cannot be accurately represented in seconds without a reference instant due to the existence of leap seconds, and months cannot be represented in days or weeks for obvious reasons. It would be great to have a standard target for this type of data type.

@tmccombs
Copy link
Contributor

Days cannot be accurately represented in seconds without a reference instant due to the existence of leap seconds

That depends on what you mean by days. Unix Epoch timestamps don't include leap seconds, so incrementing the timestamp by 24*3600 always increases the time by one day. However if you want to count physical seconds, then you do need to worry about leap seconds. And if you have a scenario where you need to worry about leap seconds, then you somehow need to continually update a database of all past leap seconds, because it is impossible to predict when future leap seconds will be more than a few months in advance.

@lifthrasiir
Copy link
Contributor

lifthrasiir commented May 27, 2017

It should be noted that there should be two slightly different difference types for date and time:

  1. Created from two time points; we know that the resulting value has no ambiguity except for possible leap seconds (e.g. we already know the time zone so DST has no effect on the difference type). Note that ISO 8601 "intervals" are actually the difference plus the time point---seems that there are several different notions of "intervals" out there.
  2. Created directly; this is what we use when we are saying, e.g. "3 months before the certain time point".

Note that there should be only one difference type of the first kind while there can be multiple difference types of the second kind. So Chrono's eventual difference type of the first kind (which is definitely not time::Duration, and I think it cannot also be std::time::Duration---more on forthcoming issues) will be usable as a difference type of the second kind, but it won't be the only possible one. For example it is always possible to define RelativeMonth type which adjusts the month in the local date, and implement std::ops::Sub for appropriate combination of types. On the other hands, Chrono has explicitly made the choice to ignore leap seconds for most cases, so the leap second ambiguity in the difference type of the first kind should be not unexpected (and users are advised to use TAI or whatever to avoid that ambiguity).

It might be possible that we can just provide everything reasonable: the eventual difference type may directly support RelativeMonth for example. I had been a firm opponent to this idea, but just in case, I've read the PostgreSQL documentation and... I must say it's convenient, if not confusing. So there are essentially three fields in the interval type: year-month, day, everything else. The fractional intervals (e.g. 1.5 month) are normalized assuming 30-day months and 24-hour days at the parsing time. Otherwise overflowing months and days are not normalized, and they are only "justified" with the dedicated functions (and the same assumption about months and days).

I will keep this issue open to track support for other difference types of the second kind.

@tmccombs
Copy link
Contributor

there can be multiple difference types of the second kind

given this, I wonder if there should be a trait for this second time, so that users can easily create new types for this. For example a user could add a duration/interval that uses units of a non-Gregorian calendar, or more esoteric time units, like sidereal days. I'm not entirely sure what the interface of that trait would look like since it would need to work with Date, DateTime, NaiveTime, NaiveDate, and NaiveDateTime. My initial suggestion would be something like:

trait DurationLike {
  fn addTo(&self, src: &NaiveDateTime) -> Option<NaiveDateTime>;
  fn subFrom(&self, src: &NaiveDateTime) -> Option<NaiveDateTime>;
}

although that interface has some limitations, like the fact that it would be rather awkward to implement DurationLike with the current NaiveDateTime since the main way to add or subtract to currently is with a time:Duration.

@lifthrasiir
Copy link
Contributor

@tmccombs You don't need a separate trait, you can just impl Add<NaiveDateTime> for ObscureDuration and so on. (Rust allows for multiple implementations when generic type parameters are disjoint enough.) Difference types of the first kind should be unique because it is defined via impl Sub<NaiveDateTime> for NaiveDateTime, which output type (the associated type Sub::Output) should be unique.

@tmccombs
Copy link
Contributor

I suppose that's true. Although you would have to implement Add for every Date and Time type.

@doivosevic
Copy link

Is there any progress on this? I would really like to have a bug free to iterate over last few months

@pitdicker
Copy link
Collaborator

We now have a dedicated issue on adding a CalendarDuration type with these features: #1282.

@pitdicker pitdicker closed this as not planned Won't fix, can't repro, duplicate, stale Sep 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants