-
Notifications
You must be signed in to change notification settings - Fork 553
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
Years type implementation #900
Conversation
I believe I already made the mistake to "commit to main". I branched from main and that's the problem. I'll change that later because I don't have more time now. I decided to open the PR since I said I would. I'll fix that later, wether opening a new PR with the proper branch or another fix for this one. One thing too, is there a deadline for the 0.4.x version to be out? |
There's no deadline! Thanks for working on this, I'll take a more detailed look after you rebase on 0.4. |
ba763b7
to
9bee716
Compare
I started a simple implementation that I intend to add proper add checks once the problem is actually solved.
9bee716
to
70da849
Compare
Nice! I'm likely to work on it on the weekends,
Not a problem! I appreciate the opportunity to contribute!
Ok! I'm still in the middle of the implementation(I couldn't finish it on my first session), I wrote a few lines of code but basically it does nothing so far. But help is always welcome! you guys are very polite when helping out! Thank you for that! Also I got a bit messed up while rebasing but I think everything should be in order right now. If you guys want, I can leave a comment here once I got any of the implementations actually working. To review and improve the code. Also, during development I plan to leave comments on the code I'm working on to try and complement the code with some thoughts. Other than that I could mark the lines of code here and leave the comment here, where I would otherwise leave in the code. |
I've converted this to a draft PR, please push the "Ready for review" button once you think it's ready! |
Ok! Thank you for that! I believe I should've done it from the beginning, I'm still learning haha I would like to ask too, the checks in the end of the PR are only for my modifications? in order to merge, all of them should be ok, right? |
Yes, CI should pass. It's possible that some failures are unrelated to your changes, but should be unlikely. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just leaving some initial comments, mostly on code location
src/years.rs
Outdated
} | ||
|
||
impl NaiveDate { | ||
pub fn checked_add_years(self, years: Years) -> Option<NaiveDate> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this impl should be in naive/date.rs - you can import Years over there
src/years.rs
Outdated
pub fn checked_sub_years(self, num_years: Years) -> Option<NaiveDate> {} | ||
} | ||
|
||
// impl Add<Years> for NaiveDate {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these impls should be in the module where the target type is defined
src/years.rs
Outdated
} | ||
|
||
// almost surely there is a more precise way to implement this | ||
fn is_leap_year(year: i32) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can use ordinal flags and then use the ndays method to figure out whether the target year is a leap year or not. You can construct the ordinal flags directly from the target year itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the pointers! I'll surely make the requested changes! This one in special will be of great help! really appreciated!
I'll move the other impl blocks to the proper locations too!
I finished the implementation, it ended up a lot simpler than I first imagined but I currently don't see why not do that haha I still need to do the documentation, but the code is compiling and the simple tests I wrote are working. (I made a simple TODO docs just to run but removed from the commit so I don't forget to do it once I'm back at it).
this helped a lot and ended up pointing me to the solution haha Thank you!! I'm planning on implementing the addition of Years and I'm still thinking about how to get the difference, in complete years, between 2 dates. That specific difference between dates helps me a lot. PS: took me a while to get back to it because of life, but I should work more on it in the following days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My personal opinion is that I don't care much for the Day
and Month
types. I prefer writing date.checked_add_years(5)
over date.checked_add_years(Years::new(5))
or date + Years::new(5)
. It seems like over-using the type system to me. But others may like it 🤷.
The DateTime<Tz>
does not have the extra methods yet.
@@ -23,6 +23,8 @@ use crate::oldtime::Duration as OldDuration; | |||
use crate::DateTime; | |||
use crate::{Datelike, Weekday}; | |||
|
|||
use crate::Years; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Date
type is deprecated, better to not add new methods to it.
@@ -1248,6 +1250,23 @@ impl NaiveDate { | |||
NaiveWeek { date: *self, start } | |||
} | |||
|
|||
// I think self here is a copy, but I still have to make sure it's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a copy, you only want to take self
by reference for DateTime<Tz>
.
return Some(self); | ||
} | ||
let num_years = i32::try_from(years.0).ok()?; | ||
self.with_year(self.year() + num_years) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fail if you add 1 year to February 29th. This is different from checked_add_months
, which will fall back to the last day of the month. Shouldn't they work the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you handle integer overflow in for example self.year() + i32::MAX
?
pub fn checked_sub_years(mut self, num_years: Years) -> Option<NaiveDateTime> { | ||
self.date = self.date.checked_sub_years(num_years)?; | ||
Some(self) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NaiveDateTime
could also use Add
and Sub
implementations.
@@ -0,0 +1,58 @@ | |||
// I usually develop with this clippy flags | |||
// but I can remove once the this module is done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 when done.
clippy::unwrap_used, | ||
clippy::expect_used)] | ||
|
||
/// TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs documentation.
clippy::expect_used)] | ||
|
||
/// TODO | ||
#[derive(Debug)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make this match the derives and attributes of Month
?
return Some(self); | ||
} | ||
let num_years = i32::try_from(years.0).ok()?; | ||
self.with_year(self.year() - num_years) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above.
Yeah, I've been on the fence about the proliferation of types here -- not sure it's the best idea, even though I may have started it. (I think the original idea was that it allowed for using the operators, which does seem like nice API.) |
I was thinking we could add We can stuff the types inside a module mostly out of sight 😄. |
Closing due to inactivity, and because we may want to step away from @Rafael-Conde Thank you for working on this! |
Thank you for notifying my @pitdicker!! I recently came back to this PR and saw how much work you did! I was really impressed, a lot of time and thought!! One last recommendation as I leave this, I saw a(apparently old) discussion about what to do with invalid dates(e.g. adding a month to January 31st, should it be February 28 or March 02?) For this matter I would recommend a cpp conference video of the creator of Chrono describing how he handled that providing invalid dates and methods for resolving it to the preferred way(it was possible to yield both results from the invalid date I mentioned in the example). I'll search for the link and I'll post here or maybe in the new PR, if you folks find it useful. Keep up the good work!!! |
Thank you, and that would be interesting! I suppose we have the capability to represent an invalid date with the internal |
I started a simple implementation that I intend to add proper add checks once the problem is actually solved.
I implemented simples tests too, but there is still a lot to do. I'm currently opening the PR so discussions about the implementation can occur here and you guys can follow the progress. I believe this is semver compatible since I'm only adding a new type so I targeted the 0.4.x branch, hopefully, this type will make it into that version.
I already applied the recommendations @esheppa made in this comment on issue #416