Skip to content

Commit

Permalink
Implement OffsetDateTime::checked_to_offset
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Jun 7, 2023
1 parent eb39e1b commit 15c0d1d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 9 deletions.
23 changes: 23 additions & 0 deletions tests/offset_date_time.rs
Expand Up @@ -68,6 +68,29 @@ fn to_offset_invalid_regression() {
);
}

#[test]
fn checked_to_offset() {
assert_eq!(
datetime!(2000-01-01 0:00 UTC)
.checked_to_offset(offset!(-1))
.unwrap()
.year(),
1999,
);
assert_eq!(
PrimitiveDateTime::MAX
.assume_utc()
.checked_to_offset(offset!(+1)),
None
);
assert_eq!(
PrimitiveDateTime::MIN
.assume_utc()
.checked_to_offset(offset!(-1)),
None
);
}

#[test]
fn from_unix_timestamp() {
assert_eq!(
Expand Down
28 changes: 19 additions & 9 deletions time/src/date_time.rs
Expand Up @@ -101,10 +101,10 @@ mod sealed {

pub trait IsOffsetKindFixed:
MaybeOffset<
Self_ = offset_kind::Fixed,
MemoryOffsetType = UtcOffset,
LogicalOffsetType = UtcOffset,
>
Self_ = offset_kind::Fixed,
MemoryOffsetType = UtcOffset,
LogicalOffsetType = UtcOffset,
>
{
}
impl IsOffsetKindFixed for offset_kind::Fixed {}
Expand Down Expand Up @@ -493,6 +493,16 @@ impl<O: MaybeOffset> DateTime<O> {

// region: to offset
pub const fn to_offset(self, offset: UtcOffset) -> DateTime<offset_kind::Fixed>
where
O: HasLogicalOffset,
{
expect_opt!(
self.checked_to_offset(offset),
"local datetime out of valid range"
)
}

pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<DateTime<offset_kind::Fixed>>
where
O: HasLogicalOffset,
{
Expand All @@ -502,24 +512,24 @@ impl<O: MaybeOffset> DateTime<O> {
&& self_offset.minutes_past_hour() == offset.minutes_past_hour()
&& self_offset.seconds_past_minute() == offset.seconds_past_minute()
{
return DateTime {
return Some(DateTime {
date: self.date,
time: self.time,
offset,
};
});
}

let (year, ordinal, time) = self.to_offset_raw(offset);

if year > MAX_YEAR || year < MIN_YEAR {
panic!("local datetime out of valid range");
return None;
}

DateTime {
Some(DateTime {
date: Date::__from_ordinal_date_unchecked(year, ordinal),
time,
offset,
}
})
}

/// Equivalent to `.to_offset(UtcOffset::UTC)`, but returning the year, ordinal, and time. This
Expand Down
24 changes: 24 additions & 0 deletions time/src/offset_date_time.rs
Expand Up @@ -97,6 +97,30 @@ impl OffsetDateTime {
Self(self.0.to_offset(offset))
}

/// Convert the `OffsetDateTime` from the current [`UtcOffset`] to the provided [`UtcOffset`],
/// returning `None` if the date-time in the resulting offset is invalid.
///
/// ```rust
/// # use time::PrimitiveDateTime;
/// # use time_macros::{datetime, offset};
/// assert_eq!(
/// datetime!(2000-01-01 0:00 UTC)
/// .checked_to_offset(offset!(-1))
/// .unwrap()
/// .year(),
/// 1999,
/// );
/// assert_eq!(
/// PrimitiveDateTime::MAX
/// .assume_utc()
/// .checked_to_offset(offset!(+1)),
/// None,
/// );
/// ```
pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<Self> {
Some(Self(const_try_opt!(self.0.checked_to_offset(offset))))
}

// region: constructors
/// Create an `OffsetDateTime` from the provided Unix timestamp. Calling `.offset()` on the
/// resulting value is guaranteed to return UTC.
Expand Down

0 comments on commit 15c0d1d

Please sign in to comment.