Skip to content

Conversation

esheppa
Copy link
Collaborator

@esheppa esheppa commented Sep 23, 2022

Setting this as draft while I figure out a good way to split up the commit into manageable units

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.

Great work! Some thoughts/suggestions from an initial round of skimming.

@esheppa esheppa force-pushed the use-std-duration-v3 branch 2 times, most recently from 7729acd to 4470857 Compare September 24, 2022 13:22
@esheppa
Copy link
Collaborator Author

esheppa commented Oct 7, 2022

will move f6dceba into the proper commits once I've got the CI passing

@esheppa esheppa force-pushed the use-std-duration-v3 branch 4 times, most recently from 8961e14 to b7266a1 Compare October 8, 2022 11:31
@esheppa esheppa marked this pull request as ready for review October 8, 2022 11:55
@esheppa esheppa force-pushed the use-std-duration-v3 branch 6 times, most recently from a2b9285 to d7fa4de Compare October 11, 2022 11:18
@esheppa esheppa requested a review from djc October 11, 2022 11:21
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.

I think the constituent pieces here are looking good. In terms of the commit history, I think instead of leaving the removal of all code related to the OldTimeDelta until the end, each commit that adds implementations for Duration should also remove the similar implementations for OldTimeDelta. That way it's much easier to review if we're adding back equivalent operations.

You also added DaysDelta and MonthsDelta. It seems like these are additive (that is, they don't exactly replace equivalent functionaly that would be removed with OldTimeDelta)? If they are not additive, it would be good to demonstrate that using the same approach (removing code in the same commit as these are added).


#[derive(Clone, Copy, PartialOrd, Ord, Debug)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
/// A difference (delta) in time build using [`core::time::Duration`] and a direction
Copy link
Member

Choose a reason for hiding this comment

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

Nit: first line of the docstring should fit on one line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should be resolved in the latest force push

(time, -rhs) // safe to negate, rhs is within +/- (2^63 / 1000)
}

/// Adds given `TimeDelta` to the current time,
Copy link
Member

Choose a reason for hiding this comment

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

Nit: shorter first docstring line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

should be resolved in the latest force push

/// assert_eq!(from_hms(3, 4, 5).checked_overflowing_add(Duration::from_secs(60 * 60 * 23)),
/// Some((from_hms(2, 4, 5), Days::new(1))));
/// ```
pub fn checked_overflowing_add(&self, rhs: Duration) -> Option<(NaiveTime, Days)> {
Copy link
Member

Choose a reason for hiding this comment

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

Where's the precedent for this name? What does overflowing mean here? Conceptually it seems like checked_ and overflowing_ would usually be mutually exclusive.

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 renamed to overflowing_add_opt but perhaps there is a better option.

The original intention was to use checked because of the Option and overflowing represents the fact that it is ok for the Duration to be longer than the time to the end of the day.

// this has the effect that if the smaller time is in a leap second, we can simply remove `SECOND_AS_NANOS`
// from the frac, and then calculate as normal

match self.secs.cmp(&rhs.secs) {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this related to the TimeDelta work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This used to rely on the fact that the duration could potentially be negative or positive, now that it can't and so the situation is a bit more complex and the signed integers are harder to work with.

An option that works which is closer to the original implementation is:

let mut secs = i64::from(self.secs) - i64::from(rhs.secs);
let mut frac = i64::from(self.frac) - i64::from(rhs.frac);

// `secs` may contain a leap second yet to be counted
let adjust = match self.secs.cmp(&rhs.secs) {
    Ordering::Greater => {
        if rhs.frac >= 1_000_000_000 {
            1
        } else {
            0
        }
    }
    Ordering::Equal => 0,
    Ordering::Less => {
        if self.frac >= 1_000_000_000 {
            -1
        } else {
            0
        }
    }
};

secs += adjust;

while frac < 0 {
    frac += 1_000_000_000;
    secs -= 1;
}
match secs.cmp(&0) {
    Ordering::Equal => {
        TimeDelta::Forwards(Duration::new(0, u32::try_from(frac).unwrap()))
    }
    Ordering::Greater => {
        TimeDelta::Forwards(Duration::new(u64::try_from(secs).unwrap(), u32::try_from(frac).unwrap()))
    }
    Ordering::Less => {
        TimeDelta::Backwards(Duration::new(u64::try_from(secs.abs()).unwrap(), u32::try_from(frac.abs()).unwrap()))
    }
}

let me know which you think is better? One benefit of the other way is that it doesn't have any unwraps

@esheppa esheppa force-pushed the use-std-duration-v3 branch 3 times, most recently from 22734af to aeb8aae Compare November 1, 2022 22:33
@esheppa esheppa force-pushed the use-std-duration-v3 branch from aeb8aae to 670e133 Compare November 1, 2022 22:37
* add shims between OldTimeDelta and TimeDelta where needed
* Remove OldTimeDelta parts from NaiveTime code
* remove problematic code from Date<Tz> - this will likely be fully removed before this is merged anyway
* add shims between OldTimeDelta and TimeDelta where needed
* remove OldTimeDelta code in NaiveDate
* these are done in one commit as they are very intertwined, eg via round.rs
* removing OldTimeDelta where it is no longer used
@esheppa esheppa force-pushed the use-std-duration-v3 branch from 670e133 to 74b087f Compare November 1, 2022 23:14
@djc
Copy link
Member

djc commented Nov 2, 2022

Don't have time to review this in detail today. One question on my mind: is there some way we can start exposing parts of this change on 0.4.x already? Presumably we could just add the TimeDelta type and add methods that return it and/or Add/Sub impls that take std::time::Duration, right?

@esheppa
Copy link
Collaborator Author

esheppa commented Nov 2, 2022

can start exposing parts of this change on 0.4.x

This should be quite possible. Almost all the methods have new names as well. The PR is actually more problematic in main because we have already used the TimeDelta name. The new code without the removals could be quite cleanly applied in 0.4.x I think.

As an additional thought, what do you think about deprecating the Add / Sub impls - these don't expose the fallibility anyway (although arguably the fallibility there is primarily overflow which is already tolerated in Add/Sub impls), and then this would make the methods the primary API, meaning we can expose essentially all of this in 0.4.x.

Do you think this would be better structured as a PR to 0.4.x adding the new code, and a PR to main which removes the old code?

@djc
Copy link
Member

djc commented Nov 2, 2022

I think it would be great to first do a PR to 0.4.x which adds new API and deprecates old stuff (I forget if/how well deprecations on impl blocks work?) merge that to main and then clean up the old stuff.

Good point about Add/Sub not exposing fallibility anyway.

@pitdicker
Copy link
Collaborator

Personally I don't think an enum wrapping an u64 to pretend to be an signed integer is a good direction. Especially if we are not even using most of the range of that u64. std::time::Duration is a little more than an u64, but the principle is close.

I'm closing this PR for now because it hasn't seen any activity in the last year while it is going to need a lot of work to become merge-able.

@pitdicker pitdicker closed this Feb 2, 2024
@pitdicker pitdicker deleted the use-std-duration-v3 branch February 2, 2024 16:27
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.

3 participants