Skip to content

Commit

Permalink
Add replace_ordinal methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Jan 28, 2024
1 parent f69ef71 commit 5f8a8e4
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 27 deletions.
15 changes: 15 additions & 0 deletions tests/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,21 @@ fn replace_day() {
assert!(date!(2022 - 02 - 18).replace_day(30).is_err()); // 30 isn't a valid day in February
}

#[test]
fn replace_ordinal() {
assert_eq!(
date!(2022 - 02 - 18).replace_ordinal(1),
Ok(date!(2022 - 001))
);
assert_eq!(
date!(2024 - 02 - 29).replace_ordinal(366),
Ok(date!(2024 - 366))
);
assert!(date!(2022 - 049).replace_ordinal(0).is_err()); // 0 isn't a valid day
assert!(date!(2022 - 049).replace_ordinal(366).is_err()); // 2022 isn't a leap year
assert!(date!(2022 - 049).replace_ordinal(367).is_err()); // 367 isn't a valid day
}

#[test]
fn next_occurrence_test() {
assert_eq!(
Expand Down
95 changes: 68 additions & 27 deletions tests/offset_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,12 +450,16 @@ fn replace_year() -> Result<()> {
datetime!(2022 - 02 - 18 12:00 +01).replace_year(2019),
Ok(datetime!(2019 - 02 - 18 12:00 +01))
);
assert!(datetime!(2022 - 02 - 18 12:00 +01)
.replace_year(-1_000_000_000)
.is_err()); // -1_000_000_000 isn't a valid year
assert!(datetime!(2022 - 02 - 18 12:00 +01)
.replace_year(1_000_000_000)
.is_err()); // 1_000_000_000 isn't a valid year
assert!(
datetime!(2022 - 02 - 18 12:00 +01)
.replace_year(-1_000_000_000)
.is_err()
); // -1_000_000_000 isn't a valid year
assert!(
datetime!(2022 - 02 - 18 12:00 +01)
.replace_year(1_000_000_000)
.is_err()
); // 1_000_000_000 isn't a valid year
Ok(())
}

Expand All @@ -465,9 +469,11 @@ fn replace_month() -> Result<()> {
datetime!(2022 - 02 - 18 12:00 +01).replace_month(Month::January),
Ok(datetime!(2022 - 01 - 18 12:00 +01))
);
assert!(datetime!(2022 - 01 - 30 12:00 +01)
.replace_month(Month::February)
.is_err()); // 30 isn't a valid day in February
assert!(
datetime!(2022 - 01 - 30 12:00 +01)
.replace_month(Month::February)
.is_err()
); // 30 isn't a valid day in February
Ok(())
}

Expand All @@ -482,15 +488,40 @@ fn replace_day() -> Result<()> {
Ok(())
}

#[test]
fn replace_ordinal() {
assert_eq!(
datetime!(2022 - 02 - 18 12:00 +01).replace_ordinal(1),
Ok(datetime!(2022 - 001 12:00 +01))
);
assert_eq!(
datetime!(2024 - 02 - 29 12:00 +01).replace_ordinal(366),
Ok(datetime!(2024 - 366 12:00 +01))
);
assert!(datetime!(2022 - 049 12:00 +01).replace_ordinal(0).is_err()); // 0 isn't a valid day
assert!(
datetime!(2022 - 049 12:00 +01)
.replace_ordinal(366)
.is_err()
); // 2022 isn't a leap year
assert!(
datetime!(2022 - 049 12:00 +01)
.replace_ordinal(367)
.is_err()
); // 367 isn't a valid day
}

#[test]
fn replace_hour() -> Result<()> {
assert_eq!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_hour(7),
Ok(datetime!(2022 - 02 - 18 07:02:03.004_005_006 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_hour(24)
.is_err()); // 24 isn't a valid hour
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_hour(24)
.is_err()
); // 24 isn't a valid hour
Ok(())
}

Expand All @@ -500,9 +531,11 @@ fn replace_minute() -> Result<()> {
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_minute(7),
Ok(datetime!(2022 - 02 - 18 01:07:03.004_005_006 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_minute(60)
.is_err()); // 60 isn't a valid minute
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_minute(60)
.is_err()
); // 60 isn't a valid minute
Ok(())
}

Expand All @@ -512,9 +545,11 @@ fn replace_second() -> Result<()> {
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_second(7),
Ok(datetime!(2022 - 02 - 18 01:02:07.004_005_006 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_second(60)
.is_err()); // 60 isn't a valid second
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_second(60)
.is_err()
); // 60 isn't a valid second
Ok(())
}

Expand All @@ -524,9 +559,11 @@ fn replace_millisecond() -> Result<()> {
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_millisecond(7),
Ok(datetime!(2022 - 02 - 18 01:02:03.007 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_millisecond(1_000)
.is_err()); // 1_000 isn't a valid millisecond
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_millisecond(1_000)
.is_err()
); // 1_000 isn't a valid millisecond
Ok(())
}

Expand All @@ -536,9 +573,11 @@ fn replace_microsecond() -> Result<()> {
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_microsecond(7_008),
Ok(datetime!(2022 - 02 - 18 01:02:03.007_008 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_microsecond(1_000_000)
.is_err()); // 1_000_000 isn't a valid microsecond
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_microsecond(1_000_000)
.is_err()
); // 1_000_000 isn't a valid microsecond
Ok(())
}

Expand All @@ -548,9 +587,11 @@ fn replace_nanosecond() -> Result<()> {
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_nanosecond(7_008_009),
Ok(datetime!(2022 - 02 - 18 01:02:03.007_008_009 +01))
);
assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_nanosecond(1_000_000_000)
.is_err()); // 1_000_000_000 isn't a valid nanosecond
assert!(
datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01)
.replace_nanosecond(1_000_000_000)
.is_err()
); // 1_000_000_000 isn't a valid nanosecond
Ok(())
}

Expand Down
15 changes: 15 additions & 0 deletions tests/primitive_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,21 @@ fn replace_day() -> Result<()> {
Ok(())
}

#[test]
fn replace_ordinal() {
assert_eq!(
datetime!(2022 - 02 - 18 12:00).replace_ordinal(1),
Ok(datetime!(2022 - 001 12:00))
);
assert_eq!(
datetime!(2024 - 02 - 29 12:00).replace_ordinal(366),
Ok(datetime!(2024 - 366 12:00))
);
assert!(datetime!(2022 - 049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid day
assert!(datetime!(2022 - 049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
assert!(datetime!(2022 - 049 12:00).replace_ordinal(367).is_err()); // 367 isn't a valid day
}

#[test]
fn replace_hour() -> Result<()> {
assert_eq!(
Expand Down
28 changes: 28 additions & 0 deletions time/src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,34 @@ impl Date {
)
})
}

/// Replace the day of the year.
///
/// ```rust
/// # use time_macros::date;
/// assert_eq!(date!(2022 - 049).replace_ordinal(1), Ok(date!(2022 - 001)));
/// assert!(date!(2022 - 049).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
/// assert!(date!(2022 - 049).replace_ordinal(366).is_err()); // 2022 isn't a leap year
/// ````
#[must_use = "This method does not mutate the original `Date`."]
pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
match ordinal {
1..=365 => {}
366 if is_leap_year(self.year()) => {}
_ => {
return Err(crate::error::ComponentRange {
name: "ordinal",
minimum: 1,
maximum: days_in_year(self.year()) as _,
value: ordinal as _,
conditional_range: true,
});
}
}

// Safety: `ordinal` is in range.
Ok(unsafe { Self::__from_ordinal_date_unchecked(self.year(), ordinal) })
}
// endregion replacement
}

Expand Down
22 changes: 22 additions & 0 deletions time/src/offset_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,7 @@ impl OffsetDateTime {
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(-1_000_000_000).is_err()); // -1_000_000_000 isn't a valid year
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid year
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_year(year)).assume_offset(self.offset()))
}
Expand All @@ -1094,6 +1095,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 01 - 30 12:00 +01).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_month(month)).assume_offset(self.offset()))
}
Expand All @@ -1109,10 +1111,24 @@ impl OffsetDateTime {
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(0).is_err()); // 00 isn't a valid day
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(30).is_err()); // 30 isn't a valid day in February
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_day(day)).assume_offset(self.offset()))
}

/// Replace the day of the year.
///
/// ```rust
/// # use time_macros::datetime;
/// assert_eq!(datetime!(2022-049 12:00 +01).replace_ordinal(1), Ok(datetime!(2022-001 12:00 +01)));
/// assert!(datetime!(2022-049 12:00 +01).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
/// assert!(datetime!(2022-049 12:00 +01).replace_ordinal(366).is_err()); // 2022 isn't a leap year
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_ordinal(ordinal)).assume_offset(self.offset()))
}

/// Replace the clock hour.
///
/// ```rust
Expand All @@ -1123,6 +1139,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_hour(24).is_err()); // 24 isn't a valid hour
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_hour(hour)).assume_offset(self.offset()))
}
Expand All @@ -1137,6 +1154,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_minute(60).is_err()); // 60 isn't a valid minute
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_minute(minute)).assume_offset(self.offset()))
}
Expand All @@ -1151,6 +1169,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_second(60).is_err()); // 60 isn't a valid second
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
Ok(const_try!(self.date_time().replace_second(second)).assume_offset(self.offset()))
}
Expand All @@ -1165,6 +1184,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_millisecond(1_000).is_err()); // 1_000 isn't a valid millisecond
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_millisecond(
self,
millisecond: u16,
Expand All @@ -1185,6 +1205,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_microsecond(1_000_000).is_err()); // 1_000_000 isn't a valid microsecond
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_microsecond(
self,
microsecond: u32,
Expand All @@ -1205,6 +1226,7 @@ impl OffsetDateTime {
/// );
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_nanosecond(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond
/// ```
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
Ok(
const_try!(self.date_time().replace_nanosecond(nanosecond))
Expand Down
16 changes: 16 additions & 0 deletions time/src/primitive_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,22 @@ impl PrimitiveDateTime {
})
}

/// Replace the day of the year.
///
/// ```rust
/// # use time_macros::datetime;
/// assert_eq!(datetime!(2022-049 12:00).replace_ordinal(1), Ok(datetime!(2022-001 12:00)));
/// assert!(datetime!(2022-049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
/// assert!(datetime!(2022-049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
/// ````
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: const_try!(self.date.replace_ordinal(ordinal)),
time: self.time,
})
}

/// Replace the clock hour.
///
/// ```rust
Expand Down

0 comments on commit 5f8a8e4

Please sign in to comment.