diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 2fbc57f8e4..e68fc3df1f 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -1026,12 +1026,15 @@ impl Datelike for DateTime { /// # Errors /// /// Returns `None` if: - /// - The resulting date does not exist. - /// - When the `NaiveDateTime` would be out of range. /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. + /// - The resulting UTC datetime would be out of range. + /// - The resulting local datetime would be out of range (unless the year remains the same). fn with_year(&self, year: i32) -> Option> { - map_local(self, |datetime| datetime.with_year(year)) + map_local(self, |dt| match dt.year() == year { + true => Some(dt), + false => dt.with_year(year), + }) } /// Makes a new `DateTime` with the month number (starting from 1) changed. diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index c679e12a23..e32a1c4a2a 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -1410,6 +1410,7 @@ fn test_min_max_setters() { let beyond_max = offset_max.from_utc_datetime(&NaiveDateTime::MAX); assert_eq!(beyond_min.with_year(2020).unwrap().year(), 2020); + assert_eq!(beyond_min.with_year(beyond_min.year()), Some(beyond_min)); assert_eq!(beyond_min.with_month(beyond_min.month()), Some(beyond_min)); assert_eq!(beyond_min.with_month(3), None); assert_eq!(beyond_min.with_month0(beyond_min.month0()), Some(beyond_min)); @@ -1430,6 +1431,7 @@ fn test_min_max_setters() { assert_eq!(beyond_min.with_nanosecond(0), Some(beyond_min)); assert_eq!(beyond_max.with_year(2020).unwrap().year(), 2020); + assert_eq!(beyond_max.with_year(beyond_max.year()), Some(beyond_max)); assert_eq!(beyond_max.with_month(beyond_max.month()), Some(beyond_max)); assert_eq!(beyond_max.with_month(3), None); assert_eq!(beyond_max.with_month0(beyond_max.month0()), Some(beyond_max));