From 5d476d3b74bb8c1ae2044f4406581912b3c68257 Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Sat, 17 Feb 2024 18:22:55 +0100 Subject: [PATCH 1/8] Return Result for NaiveDate --- src/datetime/mod.rs | 47 ++++++++++++++++++++++----------------- src/naive/date/mod.rs | 42 +++++++++++++++++----------------- src/naive/datetime/mod.rs | 26 +++++++++++----------- src/naive/time/mod.rs | 35 +++++++++++++++-------------- src/traits.rs | 32 +++++++++++++------------- 5 files changed, 95 insertions(+), 87 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 86ccf975fe..42af19c1a6 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -29,7 +29,7 @@ use crate::offset::{FixedOffset, Offset, TimeZone, Utc}; use crate::try_opt; #[cfg(any(feature = "clock", feature = "std"))] use crate::OutOfRange; -use crate::{Datelike, Months, TimeDelta, Timelike, Weekday}; +use crate::{Datelike, Error, Months, TimeDelta, Timelike, Weekday}; #[cfg(any(feature = "rkyv", feature = "rkyv-16", feature = "rkyv-32", feature = "rkyv-64"))] use rkyv::{Archive, Deserialize, Serialize}; @@ -669,13 +669,19 @@ impl From> for DateTime { } /// Maps the local datetime to other datetime with given conversion function. -fn map_local(dt: &DateTime, mut f: F) -> Option> +fn map_local(dt: &DateTime, mut f: F) -> Result, Error> where - F: FnMut(NaiveDateTime) -> Option, + F: FnMut(NaiveDateTime) -> Result, { - f(dt.overflowing_naive_local()) - .and_then(|datetime| dt.timezone().from_local_datetime(&datetime).single()) - .filter(|dt| dt >= &DateTime::::MIN_UTC && dt <= &DateTime::::MAX_UTC) + let dt = f(dt.overflowing_naive_local()).and_then(|datetime| { + dt.timezone().from_local_datetime(&datetime).single().ok_or_else(|| Error::InvalidArgument) + })?; + + if dt < DateTime::::MIN_UTC || dt > DateTime::::MAX_UTC { + return Err(Error::OutOfRange); + } + + Ok(dt) } impl DateTime { @@ -933,7 +939,7 @@ impl Datelike for DateTime { /// - 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. - fn with_year(&self, year: i32) -> Option> { + fn with_year(&self, year: i32) -> Result, Error> { map_local(self, |datetime| datetime.with_year(year)) } @@ -949,7 +955,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_month(&self, month: u32) -> Option> { + fn with_month(&self, month: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_month(month)) } @@ -965,7 +971,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_month0(&self, month0: u32) -> Option> { + fn with_month0(&self, month0: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_month0(month0)) } @@ -981,7 +987,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_day(&self, day: u32) -> Option> { + fn with_day(&self, day: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_day(day)) } @@ -997,7 +1003,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_day0(&self, day0: u32) -> Option> { + fn with_day0(&self, day0: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_day0(day0)) } @@ -1013,7 +1019,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_ordinal(&self, ordinal: u32) -> Option> { + fn with_ordinal(&self, ordinal: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_ordinal(ordinal)) } @@ -1029,7 +1035,7 @@ impl Datelike for DateTime { /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_ordinal0(&self, ordinal0: u32) -> Option> { + fn with_ordinal0(&self, ordinal0: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_ordinal0(ordinal0)) } } @@ -1058,12 +1064,12 @@ impl Timelike for DateTime { /// /// # Errors /// - /// Returns `None` if: + /// Returns `Err` if: /// - The value for `hour` is invalid. /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_hour(&self, hour: u32) -> Option> { + fn with_hour(&self, hour: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_hour(hour)) } @@ -1073,11 +1079,12 @@ impl Timelike for DateTime { /// /// # Errors /// + /// Returns `Err` if: /// - The value for `minute` is invalid. /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_minute(&self, min: u32) -> Option> { + fn with_minute(&self, min: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_minute(min)) } @@ -1090,18 +1097,18 @@ impl Timelike for DateTime { /// /// # Errors /// - /// Returns `None` if: + /// Returns `Err` if: /// - The value for `second` is invalid. /// - The local time at the resulting date does not exist or is ambiguous, for example during a /// daylight saving time transition. #[inline] - fn with_second(&self, sec: u32) -> Option> { + fn with_second(&self, sec: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_second(sec)) } /// Makes a new `DateTime` with nanoseconds since the whole non-leap second changed. /// - /// Returns `None` when the resulting `NaiveDateTime` would be invalid. + /// Returns `Err` when the resulting `NaiveDateTime` would be invalid. /// As with the [`NaiveDateTime::nanosecond`] method, /// the input range can exceed 1,000,000,000 for leap seconds. /// @@ -1111,7 +1118,7 @@ impl Timelike for DateTime { /// /// Returns `None` if `nanosecond >= 2,000,000,000`. #[inline] - fn with_nanosecond(&self, nano: u32) -> Option> { + fn with_nanosecond(&self, nano: u32) -> Result, Error> { map_local(self, |datetime| datetime.with_nanosecond(nano)) } } diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 822694db51..48c120eae7 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -793,13 +793,13 @@ impl NaiveDate { /// /// Returns `None` when the resulting `NaiveDate` would be invalid. #[inline] - const fn with_mdf(&self, mdf: Mdf) -> Option { + const fn with_mdf(&self, mdf: Mdf) -> Result { debug_assert!(self.year_flags().0 == mdf.year_flags().0); match mdf.ordinal() { Ok(ordinal) => { - Some(NaiveDate::from_yof((self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32)) + Ok(NaiveDate::from_yof((self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32)) } - Err(_) => None, // Non-existing date + Err(e) => Err(e), // Non-existing date } } @@ -1455,7 +1455,7 @@ impl Datelike for NaiveDate { /// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2020).is_some()); /// ``` #[inline] - fn with_year(&self, year: i32) -> Option { + 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(); @@ -1463,7 +1463,7 @@ impl Datelike for 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. @@ -1483,8 +1483,8 @@ impl Datelike for NaiveDate { /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month(2), None); // no February 30 /// ``` #[inline] - fn with_month(&self, month: u32) -> Option { - self.with_mdf(self.mdf().with_month(month).ok()?) + fn with_month(&self, month: u32) -> Result { + self.with_mdf(self.mdf().with_month(month)?) } /// Makes a new `NaiveDate` with the month number (starting from 0) changed. @@ -1505,9 +1505,9 @@ impl Datelike for NaiveDate { /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month0(1), None); // no February 30 /// ``` #[inline] - fn with_month0(&self, month0: u32) -> Option { - let month = month0.checked_add(1)?; - self.with_mdf(self.mdf().with_month(month).ok()?) + fn with_month0(&self, month0: u32) -> Result { + let month = month0.checked_add(1).ok_or(Error::InvalidArgument)?; + self.with_mdf(self.mdf().with_month(month)?) } /// Makes a new `NaiveDate` with the day of month (starting from 1) changed. @@ -1527,8 +1527,8 @@ impl Datelike for NaiveDate { /// None); // no September 31 /// ``` #[inline] - fn with_day(&self, day: u32) -> Option { - self.with_mdf(self.mdf().with_day(day).ok()?) + fn with_day(&self, day: u32) -> Result { + self.with_mdf(self.mdf().with_day(day)?) } /// Makes a new `NaiveDate` with the day of month (starting from 0) changed. @@ -1548,9 +1548,9 @@ impl Datelike for NaiveDate { /// None); // no September 31 /// ``` #[inline] - fn with_day0(&self, day0: u32) -> Option { - let day = day0.checked_add(1)?; - self.with_mdf(self.mdf().with_day(day).ok()?) + fn with_day0(&self, day0: u32) -> Result { + let day = day0.checked_add(1).ok_or(Error::InvalidArgument)?; + self.with_mdf(self.mdf().with_day(day)?) } /// Makes a new `NaiveDate` with the day of year (starting from 1) changed. @@ -1576,14 +1576,14 @@ impl Datelike for NaiveDate { /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap())); /// ``` #[inline] - fn with_ordinal(&self, ordinal: u32) -> Option { + fn with_ordinal(&self, ordinal: u32) -> Result { if ordinal == 0 || ordinal > 366 { - return None; + return Err(Error::InvalidArgument); } let yof = (self.yof() & !ORDINAL_MASK) | (ordinal << 4) as i32; match yof & OL_MASK <= MAX_OL { - true => Some(NaiveDate::from_yof(yof)), - false => None, // Does not exist: Ordinal 366 in a common year. + true => Ok(NaiveDate::from_yof(yof)), + false => Err(Error::DoesNotExist), // Does not exist: Ordinal 366 in a common year. } } @@ -1610,8 +1610,8 @@ impl Datelike for NaiveDate { /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap())); /// ``` #[inline] - fn with_ordinal0(&self, ordinal0: u32) -> Option { - let ordinal = ordinal0.checked_add(1)?; + fn with_ordinal0(&self, ordinal0: u32) -> Result { + let ordinal = ordinal0.checked_add(1).ok_or(Error::InvalidArgument)?; self.with_ordinal(ordinal) } } diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index b7e958614d..d705f36975 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -21,8 +21,8 @@ use crate::naive::{Days, IsoWeek, NaiveDate, NaiveTime}; use crate::offset::Utc; use crate::time_delta::NANOS_PER_SEC; use crate::{ - expect, ok, try_opt, DateTime, Datelike, FixedOffset, LocalResult, Months, TimeDelta, TimeZone, - Timelike, Weekday, + expect, ok, try_opt, DateTime, Datelike, Error, FixedOffset, LocalResult, Months, TimeDelta, + TimeZone, Timelike, Weekday, }; /// Tools to help serializing/deserializing `NaiveDateTime`s @@ -1238,7 +1238,7 @@ impl Datelike for NaiveDateTime { /// assert_eq!(dt.with_year(-308), Some(NaiveDate::from_ymd(-308, 9, 25).unwrap().and_hms(12, 34, 56).unwrap())); /// ``` #[inline] - fn with_year(&self, year: i32) -> Option { + fn with_year(&self, year: i32) -> Result { self.date.with_year(year).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1261,7 +1261,7 @@ impl Datelike for NaiveDateTime { /// assert_eq!(dt.with_month(2), None); // no February 30 /// ``` #[inline] - fn with_month(&self, month: u32) -> Option { + fn with_month(&self, month: u32) -> Result { self.date.with_month(month).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1285,7 +1285,7 @@ impl Datelike for NaiveDateTime { /// assert_eq!(dt.with_month0(1), None); // no February 30 /// ``` #[inline] - fn with_month0(&self, month0: u32) -> Option { + fn with_month0(&self, month0: u32) -> Result { self.date.with_month0(month0).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1307,7 +1307,7 @@ impl Datelike for NaiveDateTime { /// assert_eq!(dt.with_day(31), None); // no September 31 /// ``` #[inline] - fn with_day(&self, day: u32) -> Option { + fn with_day(&self, day: u32) -> Result { self.date.with_day(day).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1329,7 +1329,7 @@ impl Datelike for NaiveDateTime { /// assert_eq!(dt.with_day0(30), None); // no September 31 /// ``` #[inline] - fn with_day0(&self, day0: u32) -> Option { + fn with_day0(&self, day0: u32) -> Result { self.date.with_day0(day0).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1359,7 +1359,7 @@ impl Datelike for NaiveDateTime { /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap().and_hms(12, 34, 56).unwrap())); /// ``` #[inline] - fn with_ordinal(&self, ordinal: u32) -> Option { + fn with_ordinal(&self, ordinal: u32) -> Result { self.date.with_ordinal(ordinal).map(|d| NaiveDateTime { date: d, ..*self }) } @@ -1389,7 +1389,7 @@ impl Datelike for NaiveDateTime { /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap().and_hms(12, 34, 56).unwrap())); /// ``` #[inline] - fn with_ordinal0(&self, ordinal0: u32) -> Option { + fn with_ordinal0(&self, ordinal0: u32) -> Result { self.date.with_ordinal0(ordinal0).map(|d| NaiveDateTime { date: d, ..*self }) } } @@ -1484,7 +1484,7 @@ impl Timelike for NaiveDateTime { /// assert_eq!(dt.with_hour(24), None); /// ``` #[inline] - fn with_hour(&self, hour: u32) -> Option { + fn with_hour(&self, hour: u32) -> Result { self.time.with_hour(hour).map(|t| NaiveDateTime { time: t, ..*self }) } @@ -1507,7 +1507,7 @@ impl Timelike for NaiveDateTime { /// assert_eq!(dt.with_minute(60), None); /// ``` #[inline] - fn with_minute(&self, min: u32) -> Option { + fn with_minute(&self, min: u32) -> Result { self.time.with_minute(min).map(|t| NaiveDateTime { time: t, ..*self }) } @@ -1533,7 +1533,7 @@ impl Timelike for NaiveDateTime { /// assert_eq!(dt.with_second(60), None); /// ``` #[inline] - fn with_second(&self, sec: u32) -> Option { + fn with_second(&self, sec: u32) -> Result { self.time.with_second(sec).map(|t| NaiveDateTime { time: t, ..*self }) } @@ -1562,7 +1562,7 @@ impl Timelike for NaiveDateTime { /// assert_eq!(dt.with_nanosecond(2_000_000_000), None); /// ``` #[inline] - fn with_nanosecond(&self, nano: u32) -> Option { + fn with_nanosecond(&self, nano: u32) -> Result { self.time.with_nanosecond(nano).map(|t| NaiveDateTime { time: t, ..*self }) } } diff --git a/src/naive/time/mod.rs b/src/naive/time/mod.rs index b3907ad2f6..be276331da 100644 --- a/src/naive/time/mod.rs +++ b/src/naive/time/mod.rs @@ -900,17 +900,18 @@ impl Timelike for NaiveTime { /// ``` /// use chrono::{NaiveTime, Timelike}; /// - /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap(); - /// assert_eq!(dt.with_hour(7), Some(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678).unwrap())); - /// assert_eq!(dt.with_hour(24), None); + /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678)?; + /// assert_eq!(dt.with_hour(7), Ok(NaiveTime::from_hms_nano(7, 56, 4, 12_345_678)?)); + /// assert_eq!(dt.with_hour(24), Err(Error::InvalidArgument)); + /// Ok(()) /// ``` #[inline] - fn with_hour(&self, hour: u32) -> Option { + fn with_hour(&self, hour: u32) -> Result { if hour >= 24 { - return None; + return Err(Error::InvalidArgument); } let secs = hour * 3600 + self.secs % 3600; - Some(NaiveTime { secs, ..*self }) + Ok(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with the minute number changed. @@ -929,12 +930,12 @@ impl Timelike for NaiveTime { /// assert_eq!(dt.with_minute(60), None); /// ``` #[inline] - fn with_minute(&self, min: u32) -> Option { + fn with_minute(&self, min: u32) -> Result { if min >= 60 { - return None; + return Err(Error::InvalidArgument); } let secs = self.secs / 3600 * 3600 + min * 60 + self.secs % 60; - Some(NaiveTime { secs, ..*self }) + Ok(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with the second number changed. @@ -952,16 +953,16 @@ impl Timelike for NaiveTime { /// use chrono::{NaiveTime, Timelike}; /// /// let dt = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678).unwrap(); - /// assert_eq!(dt.with_second(17), Some(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678).unwrap())); - /// assert_eq!(dt.with_second(60), None); + /// assert_eq!(dt.with_second(17), Ok(NaiveTime::from_hms_nano(23, 56, 17, 12_345_678))); + /// assert_eq!(dt.with_second(60), Err(_)); /// ``` #[inline] - fn with_second(&self, sec: u32) -> Option { + fn with_second(&self, sec: u32) -> Result { if sec >= 60 { - return None; + return Err(Error::InvalidArgument); } let secs = self.secs / 60 * 60 + sec; - Some(NaiveTime { secs, ..*self }) + Ok(NaiveTime { secs, ..*self }) } /// Makes a new `NaiveTime` with nanoseconds since the whole non-leap second changed. @@ -996,11 +997,11 @@ impl Timelike for NaiveTime { /// assert_eq!(strange_leap_second.nanosecond(), 1_333_333_333); /// ``` #[inline] - fn with_nanosecond(&self, nano: u32) -> Option { + fn with_nanosecond(&self, nano: u32) -> Result { if nano >= 2_000_000_000 { - return None; + return Err(Error::InvalidArgument); } - Some(NaiveTime { frac: nano, ..*self }) + Ok(NaiveTime { frac: nano, ..*self }) } /// Returns the number of non-leap seconds past the last midnight. diff --git a/src/traits.rs b/src/traits.rs index 92f4b4107f..68ced09819 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,4 +1,4 @@ -use crate::{IsoWeek, Weekday}; +use crate::{Error, IsoWeek, Weekday}; /// The common set of methods for date component. /// @@ -116,7 +116,7 @@ pub trait Datelike: Sized { /// NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101 /// ); /// ``` - fn with_year(&self, year: i32) -> Option; + fn with_year(&self, year: i32) -> Result; /// Makes a new value with the month number (starting from 1) changed. /// @@ -161,7 +161,7 @@ pub trait Datelike: Sized { /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap(); /// assert_eq!(with_year_month_fixed(d, 2019, 1), NaiveDate::from_ymd(2019, 1, 29)); /// ``` - fn with_month(&self, month: u32) -> Option; + fn with_month(&self, month: u32) -> Result; /// Makes a new value with the month number (starting from 0) changed. /// @@ -175,7 +175,7 @@ pub trait Datelike: Sized { /// - The value for `month0` is out of range. /// /// [`DateTime`]: crate::DateTime - fn with_month0(&self, month0: u32) -> Option; + fn with_month0(&self, month0: u32) -> Result; /// Makes a new value with the day of month (starting from 1) changed. /// @@ -189,7 +189,7 @@ pub trait Datelike: Sized { /// - The value for `day` is out of range. /// /// [`DateTime`]: crate::DateTime - fn with_day(&self, day: u32) -> Option; + fn with_day(&self, day: u32) -> Result; /// Makes a new value with the day of month (starting from 0) changed. /// @@ -203,7 +203,7 @@ pub trait Datelike: Sized { /// - The value for `day0` is out of range. /// /// [`DateTime`]: crate::DateTime - fn with_day0(&self, day0: u32) -> Option; + fn with_day0(&self, day0: u32) -> Result; /// Makes a new value with the day of year (starting from 1) changed. /// @@ -217,7 +217,7 @@ pub trait Datelike: Sized { /// - The value for `ordinal` is out of range. /// /// [`DateTime`]: crate::DateTime - fn with_ordinal(&self, ordinal: u32) -> Option; + fn with_ordinal(&self, ordinal: u32) -> Result; /// Makes a new value with the day of year (starting from 0) changed. /// @@ -231,7 +231,7 @@ pub trait Datelike: Sized { /// - The value for `ordinal0` is out of range. /// /// [`DateTime`]: crate::DateTime - fn with_ordinal0(&self, ordinal0: u32) -> Option; + fn with_ordinal0(&self, ordinal0: u32) -> Result; /// Counts the days in the proleptic Gregorian calendar, with January 1, Year 1 (CE) as day 1. /// @@ -293,27 +293,27 @@ pub trait Timelike: Sized { /// Makes a new value with the hour number changed. /// - /// Returns `None` when the resulting value would be invalid. - fn with_hour(&self, hour: u32) -> Option; + /// Returns `Err` when the resulting value would be invalid. + fn with_hour(&self, hour: u32) -> Result; /// Makes a new value with the minute number changed. /// - /// Returns `None` when the resulting value would be invalid. - fn with_minute(&self, min: u32) -> Option; + /// Returns `Err` when the resulting value would be invalid. + fn with_minute(&self, min: u32) -> Result; /// Makes a new value with the second number changed. /// - /// Returns `None` when the resulting value would be invalid. + /// Returns `Err` when the resulting value would be invalid. /// As with the [`second`](#tymethod.second) method, /// the input range is restricted to 0 through 59. - fn with_second(&self, sec: u32) -> Option; + fn with_second(&self, sec: u32) -> Result; /// Makes a new value with nanoseconds since the whole non-leap second changed. /// - /// Returns `None` when the resulting value would be invalid. + /// Returns `Err` when the resulting value would be invalid. /// As with the [`nanosecond`](#tymethod.nanosecond) method, /// the input range can exceed 1,000,000,000 for leap seconds. - fn with_nanosecond(&self, nano: u32) -> Option; + fn with_nanosecond(&self, nano: u32) -> Result; /// Returns the number of non-leap seconds past the last midnight. /// From 30d7350da2a8070bdc41723dcf94dd45725a48d8 Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Sun, 18 Feb 2024 08:27:19 +0100 Subject: [PATCH 2/8] Doctest for NaiveDate::with_year --- src/naive/date/mod.rs | 35 ++++++++++++++++++++++++----------- src/traits.rs | 31 ------------------------------- 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 48c120eae7..9a8d81a3ae 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1433,26 +1433,39 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or when the `NaiveDate` would be - /// out of range. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::OutOfRange)` when year is out of range. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; + /// # use chrono::{Datelike, Error, 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())); + /// 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 good example that this method can return `None`. + /// A leap day (February 29) in a non-leap year will return `Err(Error::DoesNotExist)`. /// /// ``` - /// # use chrono::{NaiveDate, Datelike}; - /// 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::{Datelike, Error, NaiveDate}; + /// assert!(NaiveDate::from_ymd(2016, 2, 29)?.with_year(2015).is_err()); + /// 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. + /// + /// ``` + /// # use chrono::{Datelike, Error, NaiveDate}; + /// assert_ne!( + /// NaiveDate::from_yo(2020, 100).unwrap().with_year(2023)?, + /// NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101 + /// ); + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_year(&self, year: i32) -> Result { diff --git a/src/traits.rs b/src/traits.rs index 68ced09819..3df95230f5 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -85,37 +85,6 @@ pub trait Datelike: Sized { /// This method assumes you want to work on the date as a year-month-day value. Don't use it if /// you want the ordinal to stay the same after changing the year, of if you want the week and /// weekday values to stay the same. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (February 29 in a non-leap year). - /// - The year is out of range for [`NaiveDate`]. - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - /// [`NaiveDate`]: crate::NaiveDate - /// [`DateTime`]: crate::DateTime - /// - /// # Examples - /// - /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!( - /// NaiveDate::from_ymd(2020, 5, 13).unwrap().with_year(2023).unwrap(), - /// NaiveDate::from_ymd(2023, 5, 13).unwrap() - /// ); - /// // Resulting date 2023-02-29 does not exist: - /// assert!(NaiveDate::from_ymd(2020, 2, 29).unwrap().with_year(2023).is_none()); - /// - /// // Don't use `with_year` if you want the ordinal date to stay the same: - /// assert_ne!( - /// NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(), - /// NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101 - /// ); - /// ``` fn with_year(&self, year: i32) -> Result; /// Makes a new value with the month number (starting from 1) changed. From 445f91928132d6e1600ed3d616db8e3f37c64d5e Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Sun, 18 Feb 2024 16:25:12 +0100 Subject: [PATCH 3/8] Doctest for NaiveDate::with_month --- src/naive/date/mod.rs | 31 +++++++++++++++---------------- src/traits.rs | 42 ------------------------------------------ 2 files changed, 15 insertions(+), 58 deletions(-) diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 9a8d81a3ae..66f1a30715 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1434,7 +1434,7 @@ impl Datelike for NaiveDate { /// # Errors /// /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. - /// - Returns `Err(Error::OutOfRange)` when year is out of range. + /// - Returns `Err(Error::OutOfRange)` when the year is out of the supported range. /// /// # Example /// @@ -1483,17 +1483,17 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `month` is invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::InvalidArgument)` when the month is invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(10), - /// Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month(13), None); // no month 13 - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month(2), None); // no February 30 + /// # use chrono::{Error, NaiveDate, Datelike}; + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month(10), NaiveDate::from_ymd(2015, 10, 8)); + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month(13), Err(Error::InvalidArgument)); // no month 13 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30)?.with_month(2), Err(Error::DoesNotExist)); // no February 30 + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_month(&self, month: u32) -> Result { @@ -1504,18 +1504,17 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `month0` is - /// invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::InvalidArgument)` when the month invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(9), - /// Some(NaiveDate::from_ymd(2015, 10, 8).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_month0(12), None); // no month 13 - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30).unwrap().with_month0(1), None); // no February 30 + /// # use chrono::{Error, NaiveDate, Datelike}; + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month0(9), NaiveDate::from_ymd(2015, 10, 8)); + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month0(12), Err(Error::InvalidArgument)); // no month 13 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30)?.with_month0(1), Err(Error::DoesNotExist)); // no February 30 + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_month0(&self, month0: u32) -> Result { diff --git a/src/traits.rs b/src/traits.rs index 3df95230f5..e95ecf12ad 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -88,48 +88,6 @@ pub trait Datelike: Sized { fn with_year(&self, year: i32) -> Result; /// Makes a new value with the month number (starting from 1) changed. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (for example `month(4)` when day of the month is 31). - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - The value for `month` is out of range. - /// - /// [`DateTime`]: crate::DateTime - /// - /// # Examples - /// - /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!( - /// NaiveDate::from_ymd(2023, 5, 12).unwrap().with_month(9).unwrap(), - /// NaiveDate::from_ymd(2023, 9, 12).unwrap() - /// ); - /// // Resulting date 2023-09-31 does not exist: - /// assert!(NaiveDate::from_ymd(2023, 5, 31).unwrap().with_month(9).is_none()); - /// ``` - /// - /// Don't combine multiple `Datelike::with_*` methods. The intermediate value may not exist. - /// ``` - /// use chrono::{Error, NaiveDate, Datelike}; - /// - /// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option { - /// date.with_year(year)?.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 - /// - /// // Correct version: - /// fn with_year_month_fixed(date: NaiveDate, year: i32, month: u32) -> Result { - /// NaiveDate::from_ymd(year, month, date.day()) - /// } - /// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap(); - /// assert_eq!(with_year_month_fixed(d, 2019, 1), NaiveDate::from_ymd(2019, 1, 29)); - /// ``` fn with_month(&self, month: u32) -> Result; /// Makes a new value with the month number (starting from 0) changed. From 5f344656cd8d34493b109d367b4fb0186a0f6367 Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Sun, 18 Feb 2024 16:36:15 +0100 Subject: [PATCH 4/8] Doctest for NaiveDate::with_day --- src/naive/date/mod.rs | 40 +++++++++++++++++++++++----------------- src/traits.rs | 33 --------------------------------- 2 files changed, 23 insertions(+), 50 deletions(-) diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 66f1a30715..9f0daf2c93 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1505,15 +1505,17 @@ impl Datelike for NaiveDate { /// # Errors /// /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. - /// - Returns `Err(Error::InvalidArgument)` when the month invalid. + /// - Returns `Err(Error::InvalidArgument)` when the month is invalid. /// /// # Example /// /// ``` /// # use chrono::{Error, NaiveDate, Datelike}; /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month0(9), NaiveDate::from_ymd(2015, 10, 8)); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month0(12), Err(Error::InvalidArgument)); // no month 13 - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30)?.with_month0(1), Err(Error::DoesNotExist)); // no February 30 + /// // no month 13 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_month0(12), Err(Error::InvalidArgument)); + /// // no February 30 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 30)?.with_month0(1), Err(Error::DoesNotExist)); /// # Ok::<(), Error>(()) /// ``` #[inline] @@ -1526,17 +1528,19 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `day` is invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::InvalidArgument)` when the day is invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(30), - /// Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day(31), - /// None); // no September 31 + /// # use chrono::{Error, NaiveDate, Datelike}; + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day(30), NaiveDate::from_ymd(2015, 9, 30)); + /// // no day 32 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day(32), Err(Error::InvalidArgument)); + /// // no September 31 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day(31), Err(Error::DoesNotExist)); + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_day(&self, day: u32) -> Result { @@ -1547,17 +1551,19 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `day0` is invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::InvalidArgument)` when the day is invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(29), - /// Some(NaiveDate::from_ymd(2015, 9, 30).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8).unwrap().with_day0(30), - /// None); // no September 31 + /// # use chrono::{Error, NaiveDate, Datelike}; + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day0(29), NaiveDate::from_ymd(2015, 9, 30)); + /// // no day 32 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day0(31), Err(Error::InvalidArgument)); + /// // no September 31 + /// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_day0(30), Err(Error::DoesNotExist)); + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_day0(&self, day0: u32) -> Result { diff --git a/src/traits.rs b/src/traits.rs index e95ecf12ad..7101e952cc 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -91,45 +91,12 @@ pub trait Datelike: Sized { fn with_month(&self, month: u32) -> Result; /// Makes a new value with the month number (starting from 0) changed. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (for example `month0(3)` when day of the month is 31). - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - The value for `month0` is out of range. - /// - /// [`DateTime`]: crate::DateTime fn with_month0(&self, month0: u32) -> Result; /// Makes a new value with the day of month (starting from 1) changed. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (for example `day(31)` in April). - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - The value for `day` is out of range. - /// - /// [`DateTime`]: crate::DateTime fn with_day(&self, day: u32) -> Result; /// Makes a new value with the day of month (starting from 0) changed. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (for example `day0(30)` in April). - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - The value for `day0` is out of range. - /// - /// [`DateTime`]: crate::DateTime fn with_day0(&self, day0: u32) -> Result; /// Makes a new value with the day of year (starting from 1) changed. From 4032110dcdd4c182de3551b589488ae452577f44 Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Mon, 19 Feb 2024 10:09:57 +0100 Subject: [PATCH 5/8] Add with_ordinal --- src/naive/date/mod.rs | 54 ++++++++++++++++++++++--------------------- src/traits.rs | 11 --------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 9f0daf2c93..9355e8cdc7 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1575,23 +1575,24 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `ordinal` is - /// invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::OutOfRange)` when the ordinal is invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(60), - /// Some(NaiveDate::from_ymd(2015, 3, 1).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal(366), - /// None); // 2015 had only 365 days - /// - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(60), - /// Some(NaiveDate::from_ymd(2016, 2, 29).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal(366), - /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap())); + /// # use chrono::{Error, NaiveDate, Datelike}; + /// // 60th day in 2015 + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal(60), NaiveDate::from_ymd(2015, 3, 1)); + /// // 60th day in 2016 + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(60), NaiveDate::from_ymd(2016, 2, 29)); + /// // 366th day in 2016 (leap year) + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(366), NaiveDate::from_ymd(2016, 12, 31)); + /// // 2015 had only 365 days (non leap year) + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal(366), Err(Error::DoesNotExist)); + /// // 367th day in 2016 + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(367), Err(Error::InvalidArgument)); + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_ordinal(&self, ordinal: u32) -> Result { @@ -1609,23 +1610,24 @@ impl Datelike for NaiveDate { /// /// # Errors /// - /// Returns `None` if the resulting date does not exist, or if the value for `ordinal0` is - /// invalid. + /// - Returns `Err(Error::DoesNotExist)` when the resulting date does not exist. + /// - Returns `Err(Error::InvalidArgument)` when the ordinal is invalid. /// /// # Example /// /// ``` - /// use chrono::{NaiveDate, Datelike}; - /// - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2015, 3, 1).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1).unwrap().with_ordinal0(365), - /// None); // 2015 had only 365 days - /// - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(59), - /// Some(NaiveDate::from_ymd(2016, 2, 29).unwrap())); - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1).unwrap().with_ordinal0(365), - /// Some(NaiveDate::from_ymd(2016, 12, 31).unwrap())); + /// # use chrono::{Error, NaiveDate, Datelike}; + /// // 60th day in 2015 + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal0(59), NaiveDate::from_ymd(2015, 3, 1)); + /// // 60th day in 2016 + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(59), NaiveDate::from_ymd(2016, 2, 29)); + /// // 366th day in 2016 (leap year) + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(365), NaiveDate::from_ymd(2016, 12, 31)); + /// // 2015 had only 365 days (non leap year) + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal0(365), Err(Error::DoesNotExist)); + /// // 367th day in 2016 + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(366), Err(Error::InvalidArgument)); + /// # Ok::<(), Error>(()) /// ``` #[inline] fn with_ordinal0(&self, ordinal0: u32) -> Result { diff --git a/src/traits.rs b/src/traits.rs index 7101e952cc..0fbce5b09b 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -100,17 +100,6 @@ pub trait Datelike: Sized { fn with_day0(&self, day0: u32) -> Result; /// Makes a new value with the day of year (starting from 1) changed. - /// - /// # Errors - /// - /// Returns `None` when: - /// - /// - The resulting date does not exist (`with_ordinal(366)` in a non-leap year). - /// - In case of [`DateTime`] if the resulting date and time fall within a timezone - /// transition such as from DST to standard time. - /// - The value for `ordinal` is out of range. - /// - /// [`DateTime`]: crate::DateTime fn with_ordinal(&self, ordinal: u32) -> Result; /// Makes a new value with the day of year (starting from 0) changed. From e6891dd9a757ad4bded433d830ca793f69d1c1ea Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Mon, 19 Feb 2024 10:26:20 +0100 Subject: [PATCH 6/8] Verbose flow of map_local --- src/datetime/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 42af19c1a6..d2a3823d30 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -673,15 +673,17 @@ fn map_local(dt: &DateTime, mut f: F) -> Result Result, { - let dt = f(dt.overflowing_naive_local()).and_then(|datetime| { - dt.timezone().from_local_datetime(&datetime).single().ok_or_else(|| Error::InvalidArgument) - })?; + let naive_dt = f(dt.overflowing_naive_local())?; + let local_dt = match dt.timezone().from_local_datetime(&naive_dt) { + crate::LocalResult::Single(dt) => dt, + _ => return Err(Error::InvalidArgument), + }; - if dt < DateTime::::MIN_UTC || dt > DateTime::::MAX_UTC { + if local_dt < DateTime::::MIN_UTC || local_dt > DateTime::::MAX_UTC { return Err(Error::OutOfRange); } - Ok(dt) + Ok(local_dt) } impl DateTime { From 405f50a6d5fbdc4d6d3efc3a6b6ebe05bc9efd4e Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Mon, 19 Feb 2024 10:27:00 +0100 Subject: [PATCH 7/8] cargo fmt --- src/naive/date/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/naive/date/mod.rs b/src/naive/date/mod.rs index 9355e8cdc7..4731ab1420 100644 --- a/src/naive/date/mod.rs +++ b/src/naive/date/mod.rs @@ -1456,9 +1456,9 @@ impl Datelike for NaiveDate { /// 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. - /// + /// /// ``` /// # use chrono::{Datelike, Error, NaiveDate}; /// assert_ne!( @@ -1589,9 +1589,9 @@ impl Datelike for NaiveDate { /// // 366th day in 2016 (leap year) /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(366), NaiveDate::from_ymd(2016, 12, 31)); /// // 2015 had only 365 days (non leap year) - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal(366), Err(Error::DoesNotExist)); + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal(366), Err(Error::DoesNotExist)); /// // 367th day in 2016 - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(367), Err(Error::InvalidArgument)); + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal(367), Err(Error::InvalidArgument)); /// # Ok::<(), Error>(()) /// ``` #[inline] @@ -1624,9 +1624,9 @@ impl Datelike for NaiveDate { /// // 366th day in 2016 (leap year) /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(365), NaiveDate::from_ymd(2016, 12, 31)); /// // 2015 had only 365 days (non leap year) - /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal0(365), Err(Error::DoesNotExist)); + /// assert_eq!(NaiveDate::from_ymd(2015, 1, 1)?.with_ordinal0(365), Err(Error::DoesNotExist)); /// // 367th day in 2016 - /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(366), Err(Error::InvalidArgument)); + /// assert_eq!(NaiveDate::from_ymd(2016, 1, 1)?.with_ordinal0(366), Err(Error::InvalidArgument)); /// # Ok::<(), Error>(()) /// ``` #[inline] From 71d2faa9bd45c626c763102e8c9ad805759ad088 Mon Sep 17 00:00:00 2001 From: Moritz Oberhauser Date: Mon, 19 Feb 2024 10:43:42 +0100 Subject: [PATCH 8/8] started docs --- src/datetime/tests.rs | 44 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index bbcae978c5..9460ca4dd3 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -3,7 +3,9 @@ use crate::naive::{NaiveDate, NaiveTime}; use crate::offset::{FixedOffset, TimeZone, Utc}; #[cfg(feature = "clock")] use crate::offset::{Local, Offset}; -use crate::{Datelike, Days, LocalResult, Months, NaiveDateTime, TimeDelta, Timelike, Weekday}; +use crate::{ + Datelike, Days, Error, LocalResult, Months, NaiveDateTime, TimeDelta, Timelike, Weekday, +}; #[derive(Clone)] struct DstTester; @@ -1343,37 +1345,37 @@ 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_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)); - assert_eq!(beyond_min.with_month0(3), None); - assert_eq!(beyond_min.with_day(beyond_min.day()), Some(beyond_min)); - assert_eq!(beyond_min.with_day(15), None); - assert_eq!(beyond_min.with_day0(beyond_min.day0()), Some(beyond_min)); - assert_eq!(beyond_min.with_day0(15), None); - assert_eq!(beyond_min.with_ordinal(beyond_min.ordinal()), Some(beyond_min)); - assert_eq!(beyond_min.with_ordinal(200), None); - assert_eq!(beyond_min.with_ordinal0(beyond_min.ordinal0()), Some(beyond_min)); - assert_eq!(beyond_min.with_ordinal0(200), None); - assert_eq!(beyond_min.with_hour(beyond_min.hour()), Some(beyond_min)); - assert_eq!(beyond_min.with_hour(23), beyond_min.checked_add_signed(TimeDelta::hours(1))); + assert_eq!(beyond_min.with_month(beyond_min.month()), Ok(beyond_min)); + assert_eq!(beyond_min.with_month(3), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_month0(beyond_min.month0()), Ok(beyond_min)); + assert_eq!(beyond_min.with_month0(3), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_day(beyond_min.day()), Ok(beyond_min)); + assert_eq!(beyond_min.with_day(15), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_day0(beyond_min.day0()), Ok(beyond_min)); + assert_eq!(beyond_min.with_day0(15), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_ordinal(beyond_min.ordinal()), Ok(beyond_min)); + assert_eq!(beyond_min.with_ordinal(200), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_ordinal0(beyond_min.ordinal0()), Ok(beyond_min)); + assert_eq!(beyond_min.with_ordinal0(200), Err(Error::OutOfRange)); + assert_eq!(beyond_min.with_hour(beyond_min.hour()), Ok(beyond_min)); + assert_eq!(beyond_min.with_hour(23), Ok(beyond_min.checked_add_signed(TimeDelta::hours(1)).unwrap())); assert_eq!(beyond_min.with_hour(5), None); assert_eq!(beyond_min.with_minute(0), Some(beyond_min)); assert_eq!(beyond_min.with_second(0), Some(beyond_min)); 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_month(beyond_max.month()), Some(beyond_max)); + assert_eq!(beyond_max.with_month(beyond_max.month()), Ok(beyond_max)); assert_eq!(beyond_max.with_month(3), None); - assert_eq!(beyond_max.with_month0(beyond_max.month0()), Some(beyond_max)); + assert_eq!(beyond_max.with_month0(beyond_max.month0()), Ok(beyond_max)); assert_eq!(beyond_max.with_month0(3), None); - assert_eq!(beyond_max.with_day(beyond_max.day()), Some(beyond_max)); + assert_eq!(beyond_max.with_day(beyond_max.day()), Ok(beyond_max)); assert_eq!(beyond_max.with_day(15), None); - assert_eq!(beyond_max.with_day0(beyond_max.day0()), Some(beyond_max)); + assert_eq!(beyond_max.with_day0(beyond_max.day0()), Ok(beyond_max)); assert_eq!(beyond_max.with_day0(15), None); - assert_eq!(beyond_max.with_ordinal(beyond_max.ordinal()), Some(beyond_max)); + assert_eq!(beyond_max.with_ordinal(beyond_max.ordinal()), Ok(beyond_max)); assert_eq!(beyond_max.with_ordinal(200), None); - assert_eq!(beyond_max.with_ordinal0(beyond_max.ordinal0()), Some(beyond_max)); + assert_eq!(beyond_max.with_ordinal0(beyond_max.ordinal0()), Ok(beyond_max)); assert_eq!(beyond_max.with_ordinal0(200), None); assert_eq!(beyond_max.with_hour(beyond_max.hour()), Some(beyond_max)); assert_eq!(beyond_max.with_hour(0), beyond_max.checked_sub_signed(TimeDelta::hours(1)));