Skip to content

Commit 4163b3a

Browse files
committed
Convert NaiveDate::with_year to return Result
1 parent 6c68842 commit 4163b3a

File tree

4 files changed

+40
-55
lines changed

4 files changed

+40
-55
lines changed

src/datetime/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
570570
pub fn with_year(&self, year: i32) -> Option<DateTime<Tz>> {
571571
map_local(self, |dt| match dt.year() == year {
572572
true => Some(dt),
573-
false => dt.with_year(year),
573+
false => dt.with_year(year).ok(),
574574
})
575575
}
576576

src/naive/date/mod.rs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,58 +1195,51 @@ impl NaiveDate {
11951195

11961196
/// Makes a new `NaiveDate` with the year number changed, while keeping the same month and day.
11971197
///
1198-
/// This method assumes you want to work on the date as a year-month-day value. Don't use it if
1199-
/// you want the ordinal to stay the same after changing the year, of if you want the week and
1200-
/// weekday values to stay the same.
1201-
///
12021198
/// # Errors
12031199
///
1204-
/// Returns `None` if:
1205-
/// - The resulting date does not exist (February 29 in a non-leap year).
1206-
/// - The year is out of range for a `NaiveDate`.
1200+
/// - Returns [`Error::DoesNotExist`] when the resulting date does not exist.
1201+
/// - Returns [`Error::OutOfRange`] if `year` is out of range for a `NaiveDate`.
12071202
///
12081203
/// # Examples
12091204
///
12101205
/// ```
1211-
/// use chrono::NaiveDate;
1212-
///
1213-
/// assert_eq!(
1214-
/// NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(2016),
1215-
/// Some(NaiveDate::from_ymd(2016, 9, 8).unwrap())
1216-
/// );
1217-
/// assert_eq!(
1218-
/// NaiveDate::from_ymd(2015, 9, 8).unwrap().with_year(-308),
1219-
/// Some(NaiveDate::from_ymd(-308, 9, 8).unwrap())
1220-
/// );
1206+
/// # use chrono::{NaiveDate, Error};
1207+
/// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_year(2016),
1208+
/// NaiveDate::from_ymd(2016, 9, 8));
1209+
/// assert_eq!(NaiveDate::from_ymd(2015, 9, 8)?.with_year(-308),
1210+
/// NaiveDate::from_ymd(-308, 9, 8));
1211+
/// # Ok::<(), Error>(())
12211212
/// ```
12221213
///
1223-
/// A leap day (February 29) is a case where this method can return `None`.
1214+
/// A leap day (February 29) in a non-leap year will return [`Err(Error::DoesNotExist)`].
12241215
///
12251216
/// ```
1226-
/// # use chrono::NaiveDate;
1227-
/// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2015).is_none());
1228-
/// assert!(NaiveDate::from_ymd(2016, 2, 29).unwrap().with_year(2020).is_some());
1217+
/// # use chrono::{NaiveDate, Error};
1218+
/// assert!(NaiveDate::from_ymd(2016, 2, 29)?.with_year(2015).is_err());
1219+
/// assert!(NaiveDate::from_ymd(2016, 2, 29)?.with_year(2020).is_ok());
1220+
/// # Ok::<(), Error>(())
12291221
/// ```
12301222
///
1231-
/// Don't use `with_year` if you want the ordinal date to stay the same:
1223+
/// Don't use `with_year` if you want the ordinal date to stay the same.
12321224
///
12331225
/// ```
1234-
/// # use chrono::NaiveDate;
1226+
/// # use chrono::{NaiveDate, Error};
12351227
/// assert_ne!(
1236-
/// NaiveDate::from_yo(2020, 100).unwrap().with_year(2023).unwrap(),
1228+
/// NaiveDate::from_yo(2020, 100).unwrap().with_year(2023)?,
12371229
/// NaiveDate::from_yo(2023, 100).unwrap() // result is 2023-101
12381230
/// );
1231+
/// # Ok::<(), Error>(())
12391232
/// ```
12401233
#[inline]
1241-
pub const fn with_year(&self, year: i32) -> Option<NaiveDate> {
1234+
pub const fn with_year(&self, year: i32) -> Result<NaiveDate, Error> {
12421235
// we need to operate with `mdf` since we should keep the month and day number as is
12431236
let mdf = self.mdf();
12441237

12451238
// adjust the flags as needed
12461239
let flags = YearFlags::from_year(year);
12471240
let mdf = mdf.with_flags(flags);
12481241

1249-
ok!(NaiveDate::from_mdf(year, mdf))
1242+
NaiveDate::from_mdf(year, mdf)
12501243
}
12511244

12521245
/// Makes a new `NaiveDate` with the month number (starting from 1) changed.
@@ -1276,7 +1269,7 @@ impl NaiveDate {
12761269
/// use chrono::{Datelike, Error, NaiveDate};
12771270
///
12781271
/// fn with_year_month(date: NaiveDate, year: i32, month: u32) -> Option<NaiveDate> {
1279-
/// date.with_year(year)?.with_month(month)
1272+
/// date.with_year(year).ok()?.with_month(month)
12801273
/// }
12811274
/// let d = NaiveDate::from_ymd(2020, 2, 29).unwrap();
12821275
/// assert!(with_year_month(d, 2019, 1).is_none()); // fails because of invalid intermediate value

src/naive/date/tests.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,14 @@ fn test_date_weekday() {
367367
#[test]
368368
fn test_date_with_fields() {
369369
let d = NaiveDate::from_ymd(2000, 2, 29).unwrap();
370-
assert_eq!(d.with_year(-400), Some(NaiveDate::from_ymd(-400, 2, 29).unwrap()));
371-
assert_eq!(d.with_year(-100), None);
372-
assert_eq!(d.with_year(1600), Some(NaiveDate::from_ymd(1600, 2, 29).unwrap()));
373-
assert_eq!(d.with_year(1900), None);
374-
assert_eq!(d.with_year(2000), Some(NaiveDate::from_ymd(2000, 2, 29).unwrap()));
375-
assert_eq!(d.with_year(2001), None);
376-
assert_eq!(d.with_year(2004), Some(NaiveDate::from_ymd(2004, 2, 29).unwrap()));
377-
assert_eq!(d.with_year(i32::MAX), None);
370+
assert_eq!(d.with_year(-400), NaiveDate::from_ymd(-400, 2, 29));
371+
assert_eq!(d.with_year(-100), Err(Error::DoesNotExist));
372+
assert_eq!(d.with_year(1600), NaiveDate::from_ymd(1600, 2, 29));
373+
assert_eq!(d.with_year(1900), Err(Error::DoesNotExist));
374+
assert_eq!(d.with_year(2000), NaiveDate::from_ymd(2000, 2, 29));
375+
assert_eq!(d.with_year(2001), Err(Error::DoesNotExist));
376+
assert_eq!(d.with_year(2004), NaiveDate::from_ymd(2004, 2, 29));
377+
assert_eq!(d.with_year(i32::MAX), Err(Error::OutOfRange));
378378

379379
let d = NaiveDate::from_ymd(2000, 4, 30).unwrap();
380380
assert_eq!(d.with_month(0), None);

src/naive/datetime/mod.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::format::{Fixed, Item, Numeric, Pad};
2020
use crate::naive::{Days, IsoWeek, NaiveDate, NaiveTime};
2121
use crate::offset::Utc;
2222
use crate::{
23-
expect, ok, try_opt, DateTime, Datelike, FixedOffset, LocalResult, Months, TimeDelta, TimeZone,
24-
Timelike, Weekday,
23+
expect, ok, try_err, try_opt, DateTime, Datelike, Error, FixedOffset, LocalResult, Months,
24+
TimeDelta, TimeZone, Timelike, Weekday,
2525
};
2626

2727
/// Tools to help serializing/deserializing `NaiveDateTime`s
@@ -728,28 +728,20 @@ impl NaiveDateTime {
728728
///
729729
/// # Errors
730730
///
731-
/// Returns `None` if:
732-
/// - The resulting date does not exist (February 29 in a non-leap year).
733-
/// - The year is out of range for a `NaiveDate`.
731+
/// - See [`NaiveDate::with_year`] if the intermediate conversion to [`NaiveDate`] fails.
732+
/// - Cannot fail on the [`NaiveTime`] component.
734733
///
735-
/// # Example
734+
/// # Examples
736735
///
737736
/// ```
738-
/// use chrono::{NaiveDate, NaiveDateTime};
739-
///
740-
/// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25).unwrap().and_hms(12, 34, 56).unwrap();
741-
/// assert_eq!(
742-
/// dt.with_year(2016),
743-
/// Some(NaiveDate::from_ymd(2016, 9, 25).unwrap().and_hms(12, 34, 56).unwrap())
744-
/// );
745-
/// assert_eq!(
746-
/// dt.with_year(-308),
747-
/// Some(NaiveDate::from_ymd(-308, 9, 25).unwrap().and_hms(12, 34, 56).unwrap())
748-
/// );
737+
/// # use chrono::{NaiveDate, NaiveDateTime, Error};
738+
/// let dt: NaiveDateTime = NaiveDate::from_ymd(2015, 9, 25)?.and_hms(12, 34, 56)?;
739+
/// assert_eq!(dt.with_year(2016), NaiveDate::from_ymd(2016, 9, 25)?.and_hms(12, 34, 56));
740+
/// # Ok::<(), Error>(())
749741
/// ```
750742
#[inline]
751-
pub const fn with_year(&self, year: i32) -> Option<NaiveDateTime> {
752-
Some(NaiveDateTime { date: try_opt!(self.date.with_year(year)), ..*self })
743+
pub const fn with_year(&self, year: i32) -> Result<NaiveDateTime, Error> {
744+
Ok(NaiveDateTime { date: try_err!(self.date.with_year(year)), ..*self })
753745
}
754746

755747
/// Makes a new `NaiveDateTime` with the month number (starting from 1) changed.

0 commit comments

Comments
 (0)