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

Morph elapsed_years() API into years_since() #707

Merged
merged 1 commit into from Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 21 additions & 26 deletions src/date.rs
Expand Up @@ -276,21 +276,16 @@ impl<Tz: TimeZone> Date<Tz> {
self.date
}

/// Retrieves the elapsed years from now to the given [`Date`].
#[cfg(feature = "clock")]
pub fn elapsed_years(&self) -> u32 {
let now = Utc::today().with_timezone(&self.timezone());

let years = if (now.month(), now.day()) < (self.month(), self.day()) {
now.year() - self.year() - 1
} else {
now.year() - self.year()
};

if years.is_positive() {
years as u32
} else {
0
/// Returns the number of whole years from the given `base` until `self`.
pub fn years_since(&self, base: Self) -> Option<u32> {
let mut years = self.year() - base.year();
if (self.month(), self.day()) < (base.month(), base.day()) {
years -= 1;
}

match years >= 0 {
true => Some(years as u32),
false => None,
djc marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down Expand Up @@ -519,23 +514,23 @@ where

#[cfg(test)]
mod tests {
use crate::consts::f64;
use crate::offset::Utc;
use crate::oldtime::Duration;
use crate::{Duration, Utc};

#[test]
#[cfg(feature = "clock")]
fn test_years_elapsed() {
const WEEKS_PER_YEAR: f32 = 52.1775;

// This is always at least one year because 1 year = 52.1775 weeks.
let one_year_ago =
Utc::today() - Duration::weeks((f64::WEEKS_PER_YEAR * 1.5).ceil() as i64);
let one_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 1.5).ceil() as i64);
// A bit more than 2 years.
let two_year_ago =
Utc::today() - Duration::weeks((f64::WEEKS_PER_YEAR * 2.5).ceil() as i64);
let two_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 2.5).ceil() as i64);

assert_eq!(Utc::today().years_since(one_year_ago), Some(1));
assert_eq!(Utc::today().years_since(two_year_ago), Some(2));

assert_eq!(one_year_ago.elapsed_years(), 1);
assert_eq!(two_year_ago.elapsed_years(), 2);
// if the given Date is later than now, the function will always return 0.
assert_eq!((Utc::today() + Duration::weeks(12)).elapsed_years(), 0);
// If the given DateTime is later than now, the function will always return 0.
let future = Utc::today() + Duration::weeks(12);
assert_eq!(Utc::today().years_since(future), None);
}
}
27 changes: 13 additions & 14 deletions src/datetime/mod.rs
Expand Up @@ -357,20 +357,19 @@ impl<Tz: TimeZone> DateTime<Tz> {
}

/// Retrieve the elapsed years from now to the given [`DateTime`].
#[cfg(feature = "clock")]
pub fn elapsed_years(&self) -> u32 {
let now = Utc::now().with_timezone(&self.timezone());

let years =
if (now.month(), now.day(), now.time()) < (self.month(), self.day(), self.time()) {
now.year() - self.year() - 1
} else {
now.year() - self.year()
};
if years.is_positive() {
years as u32
} else {
0
pub fn years_since(&self, base: Self) -> Option<u32> {
let mut years = self.year() - base.year();
let earlier_time =
(self.month(), self.day(), self.time()) < (base.month(), base.day(), base.time());

years -= match earlier_time {
true => 1,
false => 0,
};

match years >= 0 {
true => Some(years as u32),
false => None,
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions src/datetime/tests.rs
@@ -1,8 +1,6 @@
use std::time::{SystemTime, UNIX_EPOCH};

use super::DateTime;
#[cfg(feature = "clock")]
use crate::consts::f64;
use crate::naive::{NaiveDate, NaiveTime};
#[cfg(feature = "clock")]
use crate::offset::Local;
Expand Down Expand Up @@ -413,14 +411,17 @@ fn test_datetime_from_local() {
#[test]
#[cfg(feature = "clock")]
fn test_years_elapsed() {
const WEEKS_PER_YEAR: f32 = 52.1775;

// This is always at least one year because 1 year = 52.1775 weeks.
let one_year_ago = Utc::today() - Duration::weeks((f64::WEEKS_PER_YEAR * 1.5).ceil() as i64);
let one_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 1.5).ceil() as i64);
// A bit more than 2 years.
let two_year_ago = Utc::today() - Duration::weeks((f64::WEEKS_PER_YEAR * 2.5).ceil() as i64);
let two_year_ago = Utc::today() - Duration::weeks((WEEKS_PER_YEAR * 2.5).ceil() as i64);

assert_eq!(one_year_ago.elapsed_years(), 1);
assert_eq!(two_year_ago.elapsed_years(), 2);
assert_eq!(Utc::today().years_since(one_year_ago), Some(1));
assert_eq!(Utc::today().years_since(two_year_ago), Some(2));

// If the given DateTime is later than now, the function will always return 0.
assert_eq!((Utc::today() + Duration::weeks(12)).elapsed_years(), 0);
let future = Utc::today() + Duration::weeks(12);
assert_eq!(Utc::today().years_since(future), None);
}
14 changes: 0 additions & 14 deletions src/lib.rs
Expand Up @@ -508,20 +508,6 @@ pub use month::{Month, ParseMonthError};
mod traits;
pub use traits::{Datelike, Timelike};

/// Constants that can be used by all components.
pub mod consts {
/// Constants of type `f32`.
pub mod f32 {
/// Number of weeks in a year.
pub const WEEKS_PER_YEAR: f32 = 52.1775;
}
/// Constants of type `f64`.
pub mod f64 {
/// Number of weeks in a year.
pub const WEEKS_PER_YEAR: f64 = 52.1775;
}
}
Comment on lines -511 to -523
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not "imprecise". This actually very precise: https://en.wikipedia.org/wiki/Week#Definition_and_duration

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, if you define a YEAR to be a "mean year" computed across 400 years, then yes. For the conventional meaning of a year (of either 365 or 366 days) it isn't very precise.

Copy link
Contributor

Choose a reason for hiding this comment

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

So I guess it's just the naming that is incorrect

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure to understand, 365.2425 days is more precise than either 365 or 366 days.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All other things being equal I'd prefer not to expose relatively niche API surface.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not like the number of weeks in a mean year is going to change though


#[cfg(feature = "__internal_bench")]
#[doc(hidden)]
pub use naive::__BenchYearFlags;
Expand Down