diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 30057af43e..0aa4049067 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -570,7 +570,7 @@ impl DateTime { pub fn with_year(&self, year: i32) -> Option> { map_local(self, |dt| match dt.year() == year { true => Some(dt), - false => dt.with_year(year), + false => dt.with_year(year).ok(), }) } diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index ddaceb160b..dbada1447c 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1201,44 +1201,39 @@ impl NaiveDate { /// /// # Errors /// - /// Returns `None` if: - /// - The resulting date does not exist (February 29 in a non-leap year). - /// - The year is out of range for a `NaiveDate`. + /// Returns: + /// - [`Error::DoesNotExist`] if the resulting date does not exist. + /// - [`Error::OutOfRange`] if `year` is out of range for a `NaiveDate`. /// /// # Examples /// /// ``` - /// use chrono::NaiveDate; - /// - /// assert_eq!( - /// NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(2016), - /// Some(NaiveDate::from_ymd(2016, 9, 8).unwrap()) - /// ); - /// assert_eq!( - /// NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(-308), - /// Some(NaiveDate::from_ymd(-308, 9, 8).unwrap()) - /// ); + /// # use chrono::{NaiveDate, Error}; + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_year(2016), NaiveDate::from_ymd(2016, 9, 8)); + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_year(-308), NaiveDate::from_ymd(-308, 9, 8)); + /// # Ok::<(), Error>(()) /// ``` /// - /// A leap day (February 29) is a case where this method can return `None`. + /// A leap day (February 29) in a non-leap year will return [`Err(Error::DoesNotExist)`]. /// /// ``` - /// # use chrono::NaiveDate; - /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2015).is_none()); - /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2020).is_some()); + /// # use chrono::{NaiveDate, Error}; + /// assert_eq!(NaiveDate::from_ymd(2016, 2, 29)?.with_year(2015), Err(Error::DoesNotExist)); + /// assert!(NaiveDate::from_ymd(2016, 2, 29)?.with_year(2020).is_ok()); + /// # Ok::<(), Error>(()) /// ``` /// - /// Don't use `with_year` if you want the ordinal date to stay the same: + /// Don't use `with_year` if you want the ordinal date to stay the same. /// /// ``` - /// # use chrono::NaiveDate; - /// assert_ne!( - /// NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(), - /// NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101 - /// ); + /// # use chrono::{NaiveDate, Error}; + /// let date = NaiveDate::from_yo(2020, 100)?.with_year(2023); + /// assert_ne!(date, NaiveDate::from_yo(2023, 100)); + /// assert_eq!(date, NaiveDate::from_yo(2023, 99)); + /// # Ok::<(), Error>(()) /// ``` #[inline] - pub const fn with_year(&self, year: i32) -> Option { + pub const fn with_year(&self, year: i32) -> Result { // we need to operate with `mdf` since we should keep the month and day number as is let mdf = self.mdf(); @@ -1246,7 +1241,7 @@ impl NaiveDate { let flags = YearFlags::from_year(year); let mdf = mdf.with_flags(flags); - ok!(NaiveDate::from_mdf(year, mdf)) + NaiveDate::from_mdf(year, mdf) } /// Makes a new `NaiveDate` with the month number (starting from 1) changed. @@ -1276,7 +1271,7 @@ impl NaiveDate { /// use chrono::{Datelike, Error, NaiveDate}; /// /// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option { - /// date.with_year(year)?.with_month(month) + /// date.with_year(year).ok()?.with_month(month) /// } /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap(); /// assert!(with_year_month(d, 2019, 1).is_none()); // fails because of invalid intermediate value diff --git a/src/naive/date/tests.rs b/src/naive/date/tests.rs index 997345407b..27a1c2bc72 100644 --- a/src/naive/date/tests.rs +++ b/src/naive/date/tests.rs @@ -367,14 +367,14 @@ fn test_date_weekday() { #[test] fn test_date_with_fields() { let d = NaiveDate::from_ymd(2000, 2, 29).unwrap(); - assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd(-400, 2, 29).unwrap())); - assert_eq!(d.with_year(-100), None); - assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd(1600, 2, 29).unwrap())); - assert_eq!(d.with_year(1900), None); - assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd(2000, 2, 29).unwrap())); - assert_eq!(d.with_year(2001), None); - assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd(2004, 2, 29).unwrap())); - assert_eq!(d.with_year(i32::MAX), None); + assert_eq!(d.with_year(-400), NaiveDate::from_ymd(-400, 2, 29)); + assert_eq!(d.with_year(-100), Err(Error::DoesNotExist)); + assert_eq!(d.with_year(1600), NaiveDate::from_ymd(1600, 2, 29)); + assert_eq!(d.with_year(1900), Err(Error::DoesNotExist)); + assert_eq!(d.with_year(2000), NaiveDate::from_ymd(2000, 2, 29)); + assert_eq!(d.with_year(2001), Err(Error::DoesNotExist)); + assert_eq!(d.with_year(2004), NaiveDate::from_ymd(2004, 2, 29)); + assert_eq!(d.with_year(i32::MAX), Err(Error::OutOfRange)); let d = NaiveDate::from_ymd(2000, 4, 30).unwrap(); assert_eq!(d.with_month(0), None); diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index fabd577fc3..94b6af7ea2 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -728,28 +728,22 @@ impl NaiveDateTime { /// /// # Errors /// - /// Returns `None` if: - /// - The resulting date does not exist (February 29 in a non-leap year). - /// - The year is out of range for a `NaiveDate`. + /// Returns: + /// - [`Error::DoesNotExist`] if the resulting date does not exist. + /// - [`Error::OutOfRange`] if `year` is out of range for a `NaiveDate`. /// - /// # Example + /// # Examples /// /// ``` - /// use chrono::{NaiveDate, NaiveDateTime}; - /// - /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap(); - /// assert_eq!( - /// dt.with_year(2016), - /// Some(NaiveDate::from_ymd(2016, 9, 25).unwrap().and_hms(12, 34, 56).unwrap()) - /// ); - /// assert_eq!( - /// dt.with_year(-308), - /// Some(NaiveDate::from_ymd(-308, 9, 25).unwrap().and_hms(12, 34, 56).unwrap()) - /// ); + /// # use chrono::{NaiveDate, NaiveDateTime, Error}; + /// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25)?.and_hms(12, 34, 56)?; + /// assert_eq!(dt.with_year(2016), NaiveDate::from_ymd(2016, 9, 25)?.and_hms(12, 34, 56)); + /// assert_eq!(dt.with_year(-308), NaiveDate::from_ymd(-308, 9, 25)?.and_hms(12, 34, 56)); + /// # Ok::<(), Error>(()) /// ``` #[inline] - pub const fn with_year(&self, year: i32) -> Option { - Some(NaiveDateTime { date: try_opt!(self.date.with_year(year)), ..*self }) + pub const fn with_year(&self, year: i32) -> Result { + Ok(NaiveDateTime { date: try_err!(self.date.with_year(year)), ..*self }) } /// Makes a new `NaiveDateTime` with the month number (starting from 1) changed.