Skip to content

Commit

Permalink
Morph elapsed_years() API into years_since()
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Jun 8, 2022
1 parent 1d33cbc commit 4876b34
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 73 deletions.
48 changes: 10 additions & 38 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,
}
}
}
Expand Down Expand Up @@ -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);
}
}
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;
}
}

#[cfg(feature = "__internal_bench")]
#[doc(hidden)]
pub use naive::__BenchYearFlags;
Expand Down
19 changes: 19 additions & 0 deletions src/naive/datetime/tests.rs
Expand Up @@ -240,3 +240,22 @@ fn test_nanosecond_range() {
NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32)
);
}

#[test]
#[cfg(feature = "clock")]
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);
}

0 comments on commit 4876b34

Please sign in to comment.