diff --git a/src/naive/date.rs b/src/naive/date.rs index e8751c111d..ad6871480e 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -23,7 +23,7 @@ use crate::format::{Item, Numeric, Pad}; use crate::month::Months; use crate::naive::{IsoWeek, NaiveDateTime, NaiveTime}; use crate::oldtime::Duration as OldDuration; -use crate::{Datelike, Duration, Weekday}; +use crate::{Datelike, Weekday}; use super::internals::{self, DateImpl, Mdf, Of, YearFlags}; use super::isoweek; @@ -76,10 +76,10 @@ impl NaiveWeek { #[inline] #[must_use] pub fn first_day(&self) -> NaiveDate { - let start = self.start.num_days_from_monday(); - let end = self.date.weekday().num_days_from_monday(); - let days = if start > end { 7 - start + end } else { end - start }; - self.date - Duration::days(days.into()) + let start = self.start.num_days_from_monday() as i32; + let ref_day = self.date.weekday().num_days_from_monday() as i32; + let days = if start > ref_day { start - ref_day - 7 } else { start - ref_day }; + self.date.add_days(days, false).unwrap() } /// Returns a date representing the last day of the week. @@ -96,7 +96,10 @@ impl NaiveWeek { #[inline] #[must_use] pub fn last_day(&self) -> NaiveDate { - self.first_day() + Duration::days(6) + let end = self.start.pred().num_days_from_monday() as i32; + let ref_day = self.date.weekday().num_days_from_monday() as i32; + let days = if end < ref_day { end - ref_day + 7 } else { end - ref_day }; + self.date.add_days(days, false).unwrap() } /// Returns a [`RangeInclusive`] representing the whole week bounded by @@ -3005,23 +3008,31 @@ mod tests { fn test_naiveweek() { let date = NaiveDate::from_ymd_opt(2022, 5, 18).unwrap(); let asserts = vec![ - (Weekday::Mon, "2022-05-16", "2022-05-22"), - (Weekday::Tue, "2022-05-17", "2022-05-23"), - (Weekday::Wed, "2022-05-18", "2022-05-24"), - (Weekday::Thu, "2022-05-12", "2022-05-18"), - (Weekday::Fri, "2022-05-13", "2022-05-19"), - (Weekday::Sat, "2022-05-14", "2022-05-20"), - (Weekday::Sun, "2022-05-15", "2022-05-21"), + (Weekday::Mon, "Mon 2022-05-16", "Sun 2022-05-22"), + (Weekday::Tue, "Tue 2022-05-17", "Mon 2022-05-23"), + (Weekday::Wed, "Wed 2022-05-18", "Tue 2022-05-24"), + (Weekday::Thu, "Thu 2022-05-12", "Wed 2022-05-18"), + (Weekday::Fri, "Fri 2022-05-13", "Thu 2022-05-19"), + (Weekday::Sat, "Sat 2022-05-14", "Fri 2022-05-20"), + (Weekday::Sun, "Sun 2022-05-15", "Sat 2022-05-21"), ]; for (start, first_day, last_day) in asserts { let week = date.week(start); let days = week.days(); - assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%Y-%m-%d")); - assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%Y-%m-%d")); + assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%a %Y-%m-%d")); + assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%a %Y-%m-%d")); assert!(days.contains(&date)); } } + #[test] + fn test_naiveweek_min_max() { + let date_max = NaiveDate::MAX; + assert!(date_max.week(Weekday::Mon).first_day() <= date_max); + let date_min = NaiveDate::MIN; + assert!(date_min.week(Weekday::Mon).last_day() >= date_min); + } + #[test] fn test_weeks_from() { // tests per: https://github.com/chronotope/chrono/issues/961