Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions src/naive/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ impl NaiveDate {
/// ```
pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
let flags = YearFlags::from_year(year);
NaiveDate::from_mdf(year, Mdf::new(month, day, flags))
NaiveDate::from_mdf(year, Mdf::new(month, day, flags)?)
}

/// Makes a new `NaiveDate` from the [ordinal date](#ordinal-date)
Expand Down Expand Up @@ -301,7 +301,7 @@ impl NaiveDate {
/// ```
pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> {
let flags = YearFlags::from_year(year);
NaiveDate::from_of(year, Of::new(ordinal, flags))
NaiveDate::from_of(year, Of::new(ordinal, flags)?)
}

/// Makes a new `NaiveDate` from the [ISO week date](#week-date)
Expand Down Expand Up @@ -370,18 +370,18 @@ impl NaiveDate {
let prevflags = YearFlags::from_year(year - 1);
NaiveDate::from_of(
year - 1,
Of::new(weekord + prevflags.ndays() - delta, prevflags),
Of::new(weekord + prevflags.ndays() - delta, prevflags)?,
)
} else {
let ordinal = weekord - delta;
let ndays = flags.ndays();
if ordinal <= ndays {
// this year
NaiveDate::from_of(year, Of::new(ordinal, flags))
NaiveDate::from_of(year, Of::new(ordinal, flags)?)
} else {
// ordinal > ndays, next year
let nextflags = YearFlags::from_year(year + 1);
NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags))
NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags)?)
}
}
} else {
Expand Down Expand Up @@ -424,7 +424,7 @@ impl NaiveDate {
let (year_div_400, cycle) = div_mod_floor(days, 146_097);
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags))
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
}

/// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
Expand Down Expand Up @@ -615,7 +615,7 @@ impl NaiveDate {
let days = [31, feb_days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let day = Ord::min(self.day(), days[(month - 1) as usize]);

NaiveDate::from_mdf(year, Mdf::new(month as u32, day, flags))
NaiveDate::from_mdf(year, Mdf::new(month as u32, day, flags)?)
}

/// Add a duration in [`Days`] to the date
Expand Down Expand Up @@ -976,7 +976,7 @@ impl NaiveDate {

let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags))
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
}

/// Subtracts the `days` part of given `Duration` from the current date.
Expand Down Expand Up @@ -1007,7 +1007,7 @@ impl NaiveDate {

let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags))
NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
}

/// Subtracts another `NaiveDate` from the current date.
Expand Down Expand Up @@ -1429,7 +1429,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_month(&self, month: u32) -> Option<NaiveDate> {
self.with_mdf(self.mdf().with_month(month))
self.with_mdf(self.mdf().with_month(month)?)
}

/// Makes a new `NaiveDate` with the month number (starting from 0) changed.
Expand All @@ -1448,7 +1448,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
self.with_mdf(self.mdf().with_month(month0 + 1))
self.with_mdf(self.mdf().with_month(month0 + 1)?)
}

/// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
Expand All @@ -1467,7 +1467,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_day(&self, day: u32) -> Option<NaiveDate> {
self.with_mdf(self.mdf().with_day(day))
self.with_mdf(self.mdf().with_day(day)?)
}

/// Makes a new `NaiveDate` with the day of month (starting from 0) changed.
Expand All @@ -1486,7 +1486,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
self.with_mdf(self.mdf().with_day(day0 + 1))
self.with_mdf(self.mdf().with_day(day0 + 1)?)
}

/// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
Expand All @@ -1510,7 +1510,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
self.with_of(self.of().with_ordinal(ordinal))
self.with_of(self.of().with_ordinal(ordinal)?)
}

/// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
Expand All @@ -1534,7 +1534,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
self.with_of(self.of().with_ordinal(ordinal0 + 1))
self.with_of(self.of().with_ordinal(ordinal0 + 1)?)
}
}

Expand Down
152 changes: 82 additions & 70 deletions src/naive/internals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,13 @@ pub(super) struct Of(pub(crate) u32);

impl Of {
#[inline]
fn clamp_ordinal(ordinal: u32) -> u32 {
if ordinal > 366 {
0
} else {
ordinal
pub(super) fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Option<Of> {
match ordinal <= 366 {
true => Some(Of((ordinal << 4) | u32::from(flags))),
false => None,
}
}

#[inline]
pub(super) fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Of {
let ordinal = Of::clamp_ordinal(ordinal);
Of((ordinal << 4) | u32::from(flags))
}

#[inline]
pub(super) fn from_mdf(Mdf(mdf): Mdf) -> Of {
let mdl = mdf >> 3;
Expand All @@ -307,10 +300,13 @@ impl Of {
}

#[inline]
pub(super) fn with_ordinal(&self, ordinal: u32) -> Of {
let ordinal = Of::clamp_ordinal(ordinal);
pub(super) fn with_ordinal(&self, ordinal: u32) -> Option<Of> {
if ordinal > 366 {
return None;
}

let Of(of) = *self;
Of((of & 0b1111) | (ordinal << 4))
Some(Of((of & 0b1111) | (ordinal << 4)))
}

#[inline]
Expand Down Expand Up @@ -375,30 +371,13 @@ pub(super) struct Mdf(pub(super) u32);

impl Mdf {
#[inline]
fn clamp_month(month: u32) -> u32 {
if month > 12 {
0
} else {
month
pub(super) fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Option<Mdf> {
match month <= 12 && day <= 31 {
true => Some(Mdf((month << 9) | (day << 4) | u32::from(flags))),
false => None,
}
}

#[inline]
fn clamp_day(day: u32) -> u32 {
if day > 31 {
0
} else {
day
}
}

#[inline]
pub(super) fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Mdf {
let month = Mdf::clamp_month(month);
let day = Mdf::clamp_day(day);
Mdf((month << 9) | (day << 4) | u32::from(flags))
}

#[inline]
pub(super) fn from_of(Of(of): Of) -> Mdf {
let ol = of >> 3;
Expand All @@ -425,10 +404,13 @@ impl Mdf {
}

#[inline]
pub(super) fn with_month(&self, month: u32) -> Mdf {
let month = Mdf::clamp_month(month);
pub(super) fn with_month(&self, month: u32) -> Option<Mdf> {
if month > 12 {
return None;
}

let Mdf(mdf) = *self;
Mdf((mdf & 0b1_1111_1111) | (month << 9))
Some(Mdf((mdf & 0b1_1111_1111) | (month << 9)))
}

#[inline]
Expand All @@ -438,10 +420,13 @@ impl Mdf {
}

#[inline]
pub(super) fn with_day(&self, day: u32) -> Mdf {
let day = Mdf::clamp_day(day);
pub(super) fn with_day(&self, day: u32) -> Option<Mdf> {
if day > 31 {
return None;
}

let Mdf(mdf) = *self;
Mdf((mdf & !0b1_1111_0000) | (day << 4))
Some(Mdf((mdf & !0b1_1111_0000) | (day << 4)))
}

#[inline]
Expand Down Expand Up @@ -523,7 +508,12 @@ mod tests {
fn test_of() {
fn check(expected: bool, flags: YearFlags, ordinal1: u32, ordinal2: u32) {
for ordinal in range_inclusive(ordinal1, ordinal2) {
let of = Of::new(ordinal, flags);
let of = match Of::new(ordinal, flags) {
Some(of) => of,
None if !expected => continue,
None => panic!("Of::new({}, {:?}) returned None", ordinal, flags),
};

assert!(
of.valid() == expected,
"ordinal {} = {:?} should be {} for dominical year {:?}",
Expand Down Expand Up @@ -555,7 +545,12 @@ mod tests {
fn check(expected: bool, flags: YearFlags, month1: u32, day1: u32, month2: u32, day2: u32) {
for month in range_inclusive(month1, month2) {
for day in range_inclusive(day1, day2) {
let mdf = Mdf::new(month, day, flags);
let mdf = match Mdf::new(month, day, flags) {
Some(mdf) => mdf,
None if !expected => continue,
None => panic!("Mdf::new({}, {}, {:?}) returned None", month, day, flags),
};

assert!(
mdf.valid() == expected,
"month {} day {} = {:?} should be {} for dominical year {:?}",
Expand Down Expand Up @@ -640,7 +635,7 @@ mod tests {
fn test_of_fields() {
for &flags in FLAGS.iter() {
for ordinal in range_inclusive(1u32, 366) {
let of = Of::new(ordinal, flags);
let of = Of::new(ordinal, flags).unwrap();
if of.valid() {
assert_eq!(of.ordinal(), ordinal);
}
Expand All @@ -651,11 +646,16 @@ mod tests {
#[test]
fn test_of_with_fields() {
fn check(flags: YearFlags, ordinal: u32) {
let of = Of::new(ordinal, flags);
let of = Of::new(ordinal, flags).unwrap();

for ordinal in range_inclusive(0u32, 1024) {
let of = of.with_ordinal(ordinal);
assert_eq!(of.valid(), Of::new(ordinal, flags).valid());
let of = match of.with_ordinal(ordinal) {
Some(of) => of,
None if ordinal > 366 => continue,
None => panic!("failed to create Of with ordinal {}", ordinal),
};

assert_eq!(of.valid(), Of::new(ordinal, flags).unwrap().valid());
if of.valid() {
assert_eq!(of.ordinal(), ordinal);
}
Expand All @@ -674,25 +674,25 @@ mod tests {

#[test]
fn test_of_weekday() {
assert_eq!(Of::new(1, A).weekday(), Weekday::Sun);
assert_eq!(Of::new(1, B).weekday(), Weekday::Sat);
assert_eq!(Of::new(1, C).weekday(), Weekday::Fri);
assert_eq!(Of::new(1, D).weekday(), Weekday::Thu);
assert_eq!(Of::new(1, E).weekday(), Weekday::Wed);
assert_eq!(Of::new(1, F).weekday(), Weekday::Tue);
assert_eq!(Of::new(1, G).weekday(), Weekday::Mon);
assert_eq!(Of::new(1, AG).weekday(), Weekday::Sun);
assert_eq!(Of::new(1, BA).weekday(), Weekday::Sat);
assert_eq!(Of::new(1, CB).weekday(), Weekday::Fri);
assert_eq!(Of::new(1, DC).weekday(), Weekday::Thu);
assert_eq!(Of::new(1, ED).weekday(), Weekday::Wed);
assert_eq!(Of::new(1, FE).weekday(), Weekday::Tue);
assert_eq!(Of::new(1, GF).weekday(), Weekday::Mon);
assert_eq!(Of::new(1, A).unwrap().weekday(), Weekday::Sun);
assert_eq!(Of::new(1, B).unwrap().weekday(), Weekday::Sat);
assert_eq!(Of::new(1, C).unwrap().weekday(), Weekday::Fri);
assert_eq!(Of::new(1, D).unwrap().weekday(), Weekday::Thu);
assert_eq!(Of::new(1, E).unwrap().weekday(), Weekday::Wed);
assert_eq!(Of::new(1, F).unwrap().weekday(), Weekday::Tue);
assert_eq!(Of::new(1, G).unwrap().weekday(), Weekday::Mon);
assert_eq!(Of::new(1, AG).unwrap().weekday(), Weekday::Sun);
assert_eq!(Of::new(1, BA).unwrap().weekday(), Weekday::Sat);
assert_eq!(Of::new(1, CB).unwrap().weekday(), Weekday::Fri);
assert_eq!(Of::new(1, DC).unwrap().weekday(), Weekday::Thu);
assert_eq!(Of::new(1, ED).unwrap().weekday(), Weekday::Wed);
assert_eq!(Of::new(1, FE).unwrap().weekday(), Weekday::Tue);
assert_eq!(Of::new(1, GF).unwrap().weekday(), Weekday::Mon);

for &flags in FLAGS.iter() {
let mut prev = Of::new(1, flags).weekday();
let mut prev = Of::new(1, flags).unwrap().weekday();
for ordinal in range_inclusive(2u32, flags.ndays()) {
let of = Of::new(ordinal, flags);
let of = Of::new(ordinal, flags).unwrap();
let expected = prev.succ();
assert_eq!(of.weekday(), expected);
prev = expected;
Expand All @@ -705,7 +705,11 @@ mod tests {
for &flags in FLAGS.iter() {
for month in range_inclusive(1u32, 12) {
for day in range_inclusive(1u32, 31) {
let mdf = Mdf::new(month, day, flags);
let mdf = match Mdf::new(month, day, flags) {
Some(mdf) => mdf,
None => continue,
};

if mdf.valid() {
assert_eq!(mdf.month(), month);
assert_eq!(mdf.day(), day);
Expand All @@ -718,20 +722,28 @@ mod tests {
#[test]
fn test_mdf_with_fields() {
fn check(flags: YearFlags, month: u32, day: u32) {
let mdf = Mdf::new(month, day, flags);
let mdf = Mdf::new(month, day, flags).unwrap();

for month in range_inclusive(0u32, 16) {
let mdf = mdf.with_month(month);
assert_eq!(mdf.valid(), Mdf::new(month, day, flags).valid());
let mdf = match mdf.with_month(month) {
Some(mdf) => mdf,
None if month > 12 => continue,
None => panic!("failed to create Mdf with month {}", month),
};

if mdf.valid() {
assert_eq!(mdf.month(), month);
assert_eq!(mdf.day(), day);
}
}

for day in range_inclusive(0u32, 1024) {
let mdf = mdf.with_day(day);
assert_eq!(mdf.valid(), Mdf::new(month, day, flags).valid());
let mdf = match mdf.with_day(day) {
Some(mdf) => mdf,
None if day > 31 => continue,
None => panic!("failed to create Mdf with month {}", month),
};

if mdf.valid() {
assert_eq!(mdf.month(), month);
assert_eq!(mdf.day(), day);
Expand Down Expand Up @@ -761,7 +773,7 @@ mod tests {
fn test_of_isoweekdate_raw() {
for &flags in FLAGS.iter() {
// January 4 should be in the first week
let (week, _) = Of::new(4 /* January 4 */, flags).isoweekdate_raw();
let (week, _) = Of::new(4 /* January 4 */, flags).unwrap().isoweekdate_raw();
assert_eq!(week, 1);
}
}
Expand Down