diff --git a/src/date.rs b/src/date.rs index d6d76d8997..b221caa3af 100644 --- a/src/date.rs +++ b/src/date.rs @@ -276,21 +276,16 @@ impl Date { 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 { + 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, } } } @@ -516,26 +511,3 @@ where write!(f, "{}{}", self.naive_local(), self.offset) } } - -#[cfg(test)] -mod tests { - use crate::consts::f64; - use crate::offset::Utc; - use crate::oldtime::Duration; - - #[test] - #[cfg(feature = "clock")] - fn test_years_elapsed() { - // 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); - // A bit more than 2 years. - let two_year_ago = - Utc::today() - Duration::weeks((f64::WEEKS_PER_YEAR * 2.5).ceil() as i64); - - 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); - } -} diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index e742e591b9..cc902646e9 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -357,20 +357,19 @@ impl DateTime { } /// 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 { + 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, } } } diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index 86036040d9..2d0d80c26c 100644 --- a/src/datetime/tests.rs +++ b/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; @@ -411,16 +409,18 @@ 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); } diff --git a/src/lib.rs b/src/lib.rs index 70ade573f6..d81cfe1e51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; - } -} - #[cfg(feature = "__internal_bench")] #[doc(hidden)] pub use naive::__BenchYearFlags; diff --git a/src/naive/datetime/tests.rs b/src/naive/datetime/tests.rs index ea5f91790d..232cac910b 100644 --- a/src/naive/datetime/tests.rs +++ b/src/naive/datetime/tests.rs @@ -240,3 +240,21 @@ fn test_nanosecond_range() { NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32) ); } + +#[test] +fn test_years_elapsed() { + use crate::Utc; + 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((WEEKS_PER_YEAR * 1.5).ceil() as i64); + // A bit more than 2 years. + 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)); + + // if the given Date 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); +}