From 752e69ae1ff600304250a5da117a3dd40f99581a Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 8 Jun 2022 13:28:02 +0200 Subject: [PATCH] Morph elapsed_years() API into years_since() --- src/date.rs | 47 +++++++++++++++++++------------------------ src/datetime/mod.rs | 27 ++++++++++++------------- src/datetime/tests.rs | 15 +++++++------- src/lib.rs | 14 ------------- 4 files changed, 42 insertions(+), 61 deletions(-) diff --git a/src/date.rs b/src/date.rs index d6d76d8997..0c9b1eef4f 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, } } } @@ -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); } } 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..3b46f3f1bf 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; @@ -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); } 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;