Skip to content

Commit

Permalink
Convert NaiveDate::from_yo to return Result
Browse files Browse the repository at this point in the history
  • Loading branch information
pitdicker committed Feb 26, 2024
1 parent a8ed320 commit 4b9bc14
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 52 deletions.
6 changes: 3 additions & 3 deletions src/format/parsed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl Parsed {

(Some(year), _, &Parsed { ordinal: Some(ordinal), .. }) => {
// year, day of the year
let date = NaiveDate::from_yo(year, ordinal).ok_or(OUT_OF_RANGE)?;
let date = NaiveDate::from_yo(year, ordinal).map_err(|_| OUT_OF_RANGE)?;
(verify_ymd(date) && verify_isoweekdate(date) && verify_ordinal(date), date)
}

Expand All @@ -406,7 +406,7 @@ impl Parsed {
&Parsed { week_from_sun: Some(week_from_sun), weekday: Some(weekday), .. },
) => {
// year, week (starting at 1st Sunday), day of the week
let newyear = NaiveDate::from_yo(year, 1).ok_or(OUT_OF_RANGE)?;
let newyear = NaiveDate::from_yo(year, 1).map_err(|_| OUT_OF_RANGE)?;
let firstweek = match newyear.weekday() {
Weekday::Sun => 0,
Weekday::Mon => 6,
Expand Down Expand Up @@ -440,7 +440,7 @@ impl Parsed {
&Parsed { week_from_mon: Some(week_from_mon), weekday: Some(weekday), .. },
) => {
// year, week (starting at 1st Monday), day of the week
let newyear = NaiveDate::from_yo(year, 1).ok_or(OUT_OF_RANGE)?;
let newyear = NaiveDate::from_yo(year, 1).map_err(|_| OUT_OF_RANGE)?;
let firstweek = match newyear.weekday() {
Weekday::Sun => 1,
Weekday::Mon => 0,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
//! assert_eq!(dt, NaiveDate::from_ymd(2014, 7, 8).unwrap().and_hms(9, 10, 11).unwrap().and_local_timezone(Utc).unwrap());
//!
//! // July 8 is 188th day of the year 2014 (`o` for "ordinal")
//! assert_eq!(dt, NaiveDate::from_yo(2014, 189)?.and_hms(9, 10, 11).unwrap().and_utc());
//! assert_eq!(dt, NaiveDate::from_yo(2014, 189).unwrap().and_hms(9, 10, 11).unwrap().and_utc());
//! // July 8 is Tuesday in ISO week 28 of the year 2014.
//! assert_eq!(dt, NaiveDate::from_isoywd(2014, 28, Weekday::Tue)?.and_hms(9, 10, 11).unwrap().and_utc());
//!
Expand Down
56 changes: 32 additions & 24 deletions src/naive/date/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl arbitrary::Arbitrary<'_> for NaiveDate {
let year = u.int_in_range(MIN_YEAR..=MAX_YEAR)?;
let max_days = YearFlags::from_year(year).ndays();
let ord = u.int_in_range(1..=max_days)?;
NaiveDate::from_yo(year, ord).ok_or(arbitrary::Error::IncorrectFormat)
NaiveDate::from_yo(year, ord).map_err(|_| arbitrary::Error::IncorrectFormat)
}
}

Expand All @@ -124,18 +124,18 @@ impl NaiveDate {
year: i32,
ordinal: u32,
flags: YearFlags,
) -> Option<NaiveDate> {
) -> Result<NaiveDate, Error> {
if year < MIN_YEAR || year > MAX_YEAR {
return None; // Out-of-range
return Err(Error::OutOfRange);
}
if ordinal == 0 || ordinal > 366 {
return None; // Invalid
return Err(Error::InvalidArgument);
}
debug_assert!(YearFlags::from_year(year).0 == flags.0);
let yof = (year << 13) | (ordinal << 4) as i32 | flags.0 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), // Ordinal 366 in a common year.
}
}

Expand Down Expand Up @@ -184,28 +184,28 @@ impl NaiveDate {
///
/// # Errors
///
/// Returns `None` if:
/// - The specified ordinal day does not exist (for example 2023-366).
/// - The value for `ordinal` is invalid (for example: `0`, `400`).
/// - `year` is out of range for `NaiveDate`.
/// This method returns:
/// - [`Error::DoesNotExist`] if the specified ordinal day does not exist (for example
/// 2023-366).
/// - [`Error::InvalidArgument`] if the value for `ordinal` is invalid (for example: `0`, `400`).
/// - [`Error::OutOfRange`] if `year` is out of range for a `NaiveDate`.
///
/// # Example
///
/// ```
/// use chrono::NaiveDate;
/// use chrono::{Error, NaiveDate};
///
/// let from_yo = NaiveDate::from_yo;
///
/// assert!(from_yo(2015, 100).is_some());
/// assert!(from_yo(2015, 0).is_none());
/// assert!(from_yo(2015, 365).is_some());
/// assert!(from_yo(2015, 366).is_none());
/// assert!(from_yo(-4, 366).is_some()); // 5 BCE is a leap year
/// assert!(from_yo(400000, 1).is_none());
/// assert!(from_yo(-400000, 1).is_none());
/// assert!(from_yo(2015, 100).is_ok());
/// assert_eq!(from_yo(2015, 0), Err(Error::InvalidArgument));
/// assert!(from_yo(2015, 365).is_ok());
/// assert_eq!(from_yo(2015, 366), Err(Error::DoesNotExist));
/// assert!(from_yo(-4, 366).is_ok()); // 5 BCE is a leap year
/// assert_eq!(from_yo(400000, 1), Err(Error::OutOfRange));
/// assert_eq!(from_yo(-400000, 1), Err(Error::OutOfRange));
/// ```
#[must_use]
pub const fn from_yo(year: i32, ordinal: u32) -> Option<NaiveDate> {
pub const fn from_yo(year: i32, ordinal: u32) -> Result<NaiveDate, Error> {
let flags = YearFlags::from_year(year);
NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
}
Expand Down Expand Up @@ -285,7 +285,7 @@ impl NaiveDate {
(year + 1, ordinal - ndays, nextflags)
}
};
NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
ok!(NaiveDate::from_ordinal_and_flags(year, ordinal, flags))
}

/// Makes a new `NaiveDate` from a day's number in the proleptic Gregorian calendar, with
Expand Down Expand Up @@ -317,7 +317,11 @@ impl NaiveDate {
let cycle = days.rem_euclid(146_097);
let (year_mod_400, ordinal) = cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
ok!(NaiveDate::from_ordinal_and_flags(
year_div_400 * 400 + year_mod_400 as i32,
ordinal,
flags
))
}

/// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
Expand Down Expand Up @@ -625,7 +629,11 @@ impl NaiveDate {

let (year_mod_400, ordinal) = cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
ok!(NaiveDate::from_ordinal_and_flags(
year_div_400 * 400 + year_mod_400 as i32,
ordinal,
flags
))
}

/// Makes a new `NaiveDateTime` from the current date and given `NaiveTime`.
Expand Down Expand Up @@ -828,7 +836,7 @@ impl NaiveDate {
let new_ol = (self.yof() & OL_MASK) + (1 << 4);
match new_ol <= MAX_OL {
true => Some(NaiveDate::from_yof(self.yof() & !OL_MASK | new_ol)),
false => NaiveDate::from_yo(self.year() + 1, 1),
false => ok!(NaiveDate::from_yo(self.year() + 1, 1)),
}
}

Expand Down
48 changes: 24 additions & 24 deletions src/naive/date/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,30 +170,30 @@ fn test_date_from_yo() {
let from_yo = NaiveDate::from_yo;
let ymd = |y, m, d| NaiveDate::from_ymd(y, m, d).unwrap();

assert_eq!(from_yo(2012, 0), None);
assert_eq!(from_yo(2012, 1), Some(ymd(2012, 1, 1)));
assert_eq!(from_yo(2012, 2), Some(ymd(2012, 1, 2)));
assert_eq!(from_yo(2012, 32), Some(ymd(2012, 2, 1)));
assert_eq!(from_yo(2012, 60), Some(ymd(2012, 2, 29)));
assert_eq!(from_yo(2012, 61), Some(ymd(2012, 3, 1)));
assert_eq!(from_yo(2012, 100), Some(ymd(2012, 4, 9)));
assert_eq!(from_yo(2012, 200), Some(ymd(2012, 7, 18)));
assert_eq!(from_yo(2012, 300), Some(ymd(2012, 10, 26)));
assert_eq!(from_yo(2012, 366), Some(ymd(2012, 12, 31)));
assert_eq!(from_yo(2012, 367), None);
assert_eq!(from_yo(2012, 1 << 28 | 60), None);

assert_eq!(from_yo(2014, 0), None);
assert_eq!(from_yo(2014, 1), Some(ymd(2014, 1, 1)));
assert_eq!(from_yo(2014, 2), Some(ymd(2014, 1, 2)));
assert_eq!(from_yo(2014, 32), Some(ymd(2014, 2, 1)));
assert_eq!(from_yo(2014, 59), Some(ymd(2014, 2, 28)));
assert_eq!(from_yo(2014, 60), Some(ymd(2014, 3, 1)));
assert_eq!(from_yo(2014, 100), Some(ymd(2014, 4, 10)));
assert_eq!(from_yo(2014, 200), Some(ymd(2014, 7, 19)));
assert_eq!(from_yo(2014, 300), Some(ymd(2014, 10, 27)));
assert_eq!(from_yo(2014, 365), Some(ymd(2014, 12, 31)));
assert_eq!(from_yo(2014, 366), None);
assert_eq!(from_yo(2012, 0), Err(Error::InvalidArgument));
assert_eq!(from_yo(2012, 1), Ok(ymd(2012, 1, 1)));
assert_eq!(from_yo(2012, 2), Ok(ymd(2012, 1, 2)));
assert_eq!(from_yo(2012, 32), Ok(ymd(2012, 2, 1)));
assert_eq!(from_yo(2012, 60), Ok(ymd(2012, 2, 29)));
assert_eq!(from_yo(2012, 61), Ok(ymd(2012, 3, 1)));
assert_eq!(from_yo(2012, 100), Ok(ymd(2012, 4, 9)));
assert_eq!(from_yo(2012, 200), Ok(ymd(2012, 7, 18)));
assert_eq!(from_yo(2012, 300), Ok(ymd(2012, 10, 26)));
assert_eq!(from_yo(2012, 366), Ok(ymd(2012, 12, 31)));
assert_eq!(from_yo(2012, 367), Err(Error::InvalidArgument));
assert_eq!(from_yo(2012, 1 << 28 | 60), Err(Error::InvalidArgument));

assert_eq!(from_yo(2014, 0), Err(Error::InvalidArgument));
assert_eq!(from_yo(2014, 1), Ok(ymd(2014, 1, 1)));
assert_eq!(from_yo(2014, 2), Ok(ymd(2014, 1, 2)));
assert_eq!(from_yo(2014, 32), Ok(ymd(2014, 2, 1)));
assert_eq!(from_yo(2014, 59), Ok(ymd(2014, 2, 28)));
assert_eq!(from_yo(2014, 60), Ok(ymd(2014, 3, 1)));
assert_eq!(from_yo(2014, 100), Ok(ymd(2014, 4, 10)));
assert_eq!(from_yo(2014, 200), Ok(ymd(2014, 7, 19)));
assert_eq!(from_yo(2014, 300), Ok(ymd(2014, 10, 27)));
assert_eq!(from_yo(2014, 365), Ok(ymd(2014, 12, 31)));
assert_eq!(from_yo(2014, 366), Err(Error::DoesNotExist));
}

#[test]
Expand Down

0 comments on commit 4b9bc14

Please sign in to comment.