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 Day<Tz> #883

Closed
wants to merge 2 commits into from
Closed

add Day<Tz> #883

wants to merge 2 commits into from

Conversation

esheppa
Copy link
Collaborator

@esheppa esheppa commented Nov 19, 2022

No description provided.

Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some early feedback.

src/day.rs Outdated
Comment on lines 98 to 106
///
pub fn succ(&self) -> Option<Day<Tz>> {
Some(Day { date: self.date.succ_opt()?, tz: self.tz })
}

///
pub fn pred(&self) -> Option<Day<Tz>> {
Some(Day { date: self.date.pred_opt()?, tz: self.tz })
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned elsewhere, I kinda want to move away from providing these...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed, however these are potentially useful when dealing with non-instant style types, for example, my_day.succ().start() is an exclusive end time for my_day - but this could be implemented directly

}

///
pub fn start(&self) -> DateTime<Tz> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use some documentation of why we have to use a loop here. What problem is this trying to solve?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some more documentation here including around panics and incorrect results

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way to have this not require heuristics would be to make the loop slightly differently:

  • first, try with NaiveTime::MIN as a fast path
  • then, for each 15min segment,
    • if MIN + segment_end is not ok, go to the next segment
    • else, if MIN + segment_end - 1ns is ok too, do a dichotomy between MIN + segment_begin and MIN + segment_end

That said, I personally don't think that doing this would be necessary. Summer time changes across midnight are unlikely enough already, having them not be a multiple-of-15-min offset would be actively harmful to basically any software.

Another idea would be, to delegate the implementation of this to a new trait method on TimeZone, that would have a default implementation of adding NaiveTime::MIN; and on the day chrono_tz gets a summer time transition across midnight the specialization can be added there.

I'm personally partial towards the second idea, as it gets us all of the simplest implementation right now, the most efficient one, and the most future-proof one. Does that make sense?


impl<Tz> Eq for Day<Tz> where Tz: TimeZone + Copy + Display {}

impl<Tz> Day<Tz>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: would prefer to have the inherent impl before trait impls.

Also I would write impl<Tz: TimeZone + Copy + Display> instead of having the where clause`, since it's a bit more concise.

Comment on lines +135 to +120
///
pub fn checked_add_days(self, days: Days) -> Option<Self> {
if days.0 == 0 {
return Some(self);
}

i64::try_from(days.0).ok().and_then(|d| self.diff_days(d))
}

///
pub fn checked_sub_days(self, days: Days) -> Option<Self> {
if days.0 == 0 {
return Some(self);
}

i64::try_from(days.0).ok().and_then(|d| self.diff_days(-d))
}

fn diff_days(self, days: i64) -> Option<Self> {
let date = self.date.checked_add_signed(Duration::days(days))?;
Some(Day { date, ..self })
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like in general we should start with a minimal API here, we can grow it over time as people actually ask for it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ekleog
Copy link
Contributor

Ekleog commented Jan 27, 2023

(FWIW, I just linked a fuzzer crash from #948 ; which needs implementing basically this to fix it)

@esheppa esheppa mentioned this pull request Feb 20, 2023
@pitdicker
Copy link
Collaborator

As a summary:
Time<Tz> was removed in chrono 0.2.0, and Date<Tz> was deprecated in 0.4.23.
Operations on these didn't make all that much sense, except as a building block to create a DateTime<Tz>.

The type Day<Tz> in this PR is to fill a small gap Date<Tz> leaves in response to #820 (comment):
Day<Tz> can describe a day in some timezone Tz, with a well-defined start and end. The length of the day may be less or more than 24 hours. Essentially Day<Tz> is a special case of a Period #380.

In my opinion this type is not generally useful enough to be added. NaiveDate and TimeZone::from_local_datetime can be used to write code with the same functionality. And a type with these semantics can easily be implemented it in user code.

Also we have not had others except for the one use case in that comment ask for this functionality.

@pitdicker
Copy link
Collaborator

Closing this PR. If someone wants to push for this feature, please open an issue.

@pitdicker pitdicker closed this Jan 30, 2024
@pitdicker pitdicker deleted the add-day-tz branch January 30, 2024 17:32
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

Successfully merging this pull request may close these issues.

4 participants