diff --git a/tests/month.rs b/tests/month.rs index 6e4a1cbb1..e5354efef 100644 --- a/tests/month.rs +++ b/tests/month.rs @@ -32,6 +32,74 @@ fn next() { assert_eq!(December.next(), January); } +#[test] +fn nth_next() { + assert_eq!(January.nth_next(0), January); + assert_eq!(January.nth_next(1), February); + assert_eq!(January.nth_next(2), March); + assert_eq!(January.nth_next(3), April); + assert_eq!(January.nth_next(4), May); + assert_eq!(January.nth_next(5), June); + assert_eq!(January.nth_next(6), July); + assert_eq!(January.nth_next(7), August); + assert_eq!(January.nth_next(8), September); + assert_eq!(January.nth_next(9), October); + assert_eq!(January.nth_next(10), November); + assert_eq!(January.nth_next(11), December); + + assert_eq!(December.nth_next(0), December); + assert_eq!(December.nth_next(1), January); + assert_eq!(December.nth_next(2), February); + assert_eq!(December.nth_next(3), March); + assert_eq!(December.nth_next(4), April); + assert_eq!(December.nth_next(5), May); + assert_eq!(December.nth_next(6), June); + assert_eq!(December.nth_next(7), July); + assert_eq!(December.nth_next(8), August); + assert_eq!(December.nth_next(9), September); + assert_eq!(December.nth_next(10), October); + assert_eq!(December.nth_next(11), November); + + assert_eq!(January.nth_next(12), January); + assert_eq!(January.nth_next(u8::MAX), April); + assert_eq!(December.nth_next(12), December); + assert_eq!(December.nth_next(u8::MAX), March); +} + +#[test] +fn nth_prev() { + assert_eq!(January.nth_prev(0), January); + assert_eq!(January.nth_prev(1), December); + assert_eq!(January.nth_prev(2), November); + assert_eq!(January.nth_prev(3), October); + assert_eq!(January.nth_prev(4), September); + assert_eq!(January.nth_prev(5), August); + assert_eq!(January.nth_prev(6), July); + assert_eq!(January.nth_prev(7), June); + assert_eq!(January.nth_prev(8), May); + assert_eq!(January.nth_prev(9), April); + assert_eq!(January.nth_prev(10), March); + assert_eq!(January.nth_prev(11), February); + + assert_eq!(December.nth_prev(0), December); + assert_eq!(December.nth_prev(1), November); + assert_eq!(December.nth_prev(2), October); + assert_eq!(December.nth_prev(3), September); + assert_eq!(December.nth_prev(4), August); + assert_eq!(December.nth_prev(5), July); + assert_eq!(December.nth_prev(6), June); + assert_eq!(December.nth_prev(7), May); + assert_eq!(December.nth_prev(8), April); + assert_eq!(December.nth_prev(9), March); + assert_eq!(December.nth_prev(10), February); + assert_eq!(December.nth_prev(11), January); + + assert_eq!(January.nth_prev(12), January); + assert_eq!(January.nth_prev(u8::MAX), October); + assert_eq!(December.nth_prev(12), December); + assert_eq!(December.nth_prev(u8::MAX), September); +} + #[test] fn display() { assert_eq!(January.to_string(), "January"); diff --git a/tests/weekday.rs b/tests/weekday.rs index 7ed14e105..e6dd48a11 100644 --- a/tests/weekday.rs +++ b/tests/weekday.rs @@ -46,6 +46,30 @@ fn nth_next() { assert_eq!(Monday.nth_next(u8::MAX), Thursday); } +#[test] +fn nth_prev() { + assert_eq!(Sunday.nth_prev(0), Sunday); + assert_eq!(Sunday.nth_prev(1), Saturday); + assert_eq!(Sunday.nth_prev(2), Friday); + assert_eq!(Sunday.nth_prev(3), Thursday); + assert_eq!(Sunday.nth_prev(4), Wednesday); + assert_eq!(Sunday.nth_prev(5), Tuesday); + assert_eq!(Sunday.nth_prev(6), Monday); + + assert_eq!(Monday.nth_prev(0), Monday); + assert_eq!(Monday.nth_prev(1), Sunday); + assert_eq!(Monday.nth_prev(2), Saturday); + assert_eq!(Monday.nth_prev(3), Friday); + assert_eq!(Monday.nth_prev(4), Thursday); + assert_eq!(Monday.nth_prev(5), Wednesday); + assert_eq!(Monday.nth_prev(6), Tuesday); + + assert_eq!(Sunday.nth_prev(7), Sunday); + assert_eq!(Sunday.nth_prev(u8::MAX), Thursday); + assert_eq!(Monday.nth_prev(7), Monday); + assert_eq!(Monday.nth_prev(u8::MAX), Friday); +} + #[test] fn number_from_monday() { assert_eq!(Monday.number_from_monday(), 1); diff --git a/time/src/month.rs b/time/src/month.rs index 0c657e982..8d8c164b2 100644 --- a/time/src/month.rs +++ b/time/src/month.rs @@ -97,6 +97,60 @@ impl Month { December => January, } } + + /// Get n-th next month. + /// + /// ```rust + /// # use time::Month; + /// assert_eq!(Month::January.nth_next(4), Month::May); + /// assert_eq!(Month::July.nth_next(9), Month::April); + /// ``` + pub const fn nth_next(self, n: u8) -> Self { + match (self as u8 - 1 + n % 12) % 12 { + 0 => January, + 1 => February, + 2 => March, + 3 => April, + 4 => May, + 5 => June, + 6 => July, + 7 => August, + 8 => September, + 9 => October, + 10 => November, + val => { + debug_assert!(val == 11); + December + } + } + } + + /// Get n-th previous month. + /// + /// ```rust + /// # use time::Month; + /// assert_eq!(Month::January.nth_prev(4), Month::September); + /// assert_eq!(Month::July.nth_prev(9), Month::October); + /// ``` + pub const fn nth_prev(self, n: u8) -> Self { + match self as i8 - 1 - (n % 12) as i8 { + 1 | -11 => February, + 2 | -10 => March, + 3 | -9 => April, + 4 | -8 => May, + 5 | -7 => June, + 6 | -6 => July, + 7 | -5 => August, + 8 | -4 => September, + 9 | -3 => October, + 10 | -2 => November, + 11 | -1 => December, + val => { + debug_assert!(val == 0); + January + } + } + } } impl fmt::Display for Month { diff --git a/time/src/weekday.rs b/time/src/weekday.rs index d530a2e4d..761107e69 100644 --- a/time/src/weekday.rs +++ b/time/src/weekday.rs @@ -88,6 +88,28 @@ impl Weekday { } } + /// Get n-th previous day. + /// + /// ```rust + /// # use time::Weekday; + /// assert_eq!(Weekday::Monday.nth_prev(1), Weekday::Sunday); + /// assert_eq!(Weekday::Sunday.nth_prev(10), Weekday::Thursday); + /// ``` + pub const fn nth_prev(self, n: u8) -> Self { + match self.number_days_from_monday() as i8 - (n % 7) as i8 { + 1 | -6 => Tuesday, + 2 | -5 => Wednesday, + 3 | -4 => Thursday, + 4 | -3 => Friday, + 5 | -2 => Saturday, + 6 | -1 => Sunday, + val => { + debug_assert!(val == 0); + Monday + } + } + } + /// Get the one-indexed number of days from Monday. /// /// ```rust