diff --git a/src/offset/local/unix.rs b/src/offset/local/unix.rs index ad99542330..1ae3a6f59a 100644 --- a/src/offset/local/unix.rs +++ b/src/offset/local/unix.rs @@ -166,6 +166,6 @@ impl Cache { self.zone .find_local_time_type_from_local(d.and_utc().timestamp(), d.year()) .expect("unable to select local time type") - .map(|o| FixedOffset::east_opt(o.offset()).unwrap()) + .try_map(|o| FixedOffset::east_opt(o.offset())) } } diff --git a/src/offset/mod.rs b/src/offset/mod.rs index c1d1cc5619..56eb030cb6 100644 --- a/src/offset/mod.rs +++ b/src/offset/mod.rs @@ -121,6 +121,24 @@ impl MappedLocalTime { MappedLocalTime::Ambiguous(min, max) => MappedLocalTime::Ambiguous(f(min), f(max)), } } + + /// Maps a `MappedLocalTime` into `MappedLocalTime` with given function. + /// + /// Returns `MappedLocalTime::None` if the function returns `None`. + #[must_use] + pub(crate) fn try_map Option>(self, mut f: F) -> MappedLocalTime { + match self { + MappedLocalTime::None => MappedLocalTime::None, + MappedLocalTime::Single(v) => match f(v) { + Some(new) => MappedLocalTime::Single(new), + None => MappedLocalTime::None, + }, + MappedLocalTime::Ambiguous(min, max) => match (f(min), f(max)) { + (Some(min), Some(max)) => MappedLocalTime::Ambiguous(min, max), + _ => MappedLocalTime::None, + }, + } + } } /// The conversion result from the local time to the timezone-aware datetime types. @@ -547,26 +565,11 @@ pub trait TimeZone: Sized + Clone { /// Converts the local `NaiveDateTime` to the timezone-aware `DateTime` if possible. #[allow(clippy::wrong_self_convention)] fn from_local_datetime(&self, local: &NaiveDateTime) -> MappedLocalTime> { - // Return `MappedLocalTime::None` when the offset pushes a value out of range, instead of - // panicking. - match self.offset_from_local_datetime(local) { - MappedLocalTime::None => MappedLocalTime::None, - MappedLocalTime::Single(offset) => match local.checked_sub_offset(offset.fix()) { - Some(dt) => { - MappedLocalTime::Single(DateTime::from_naive_utc_and_offset(dt, offset)) - } - None => MappedLocalTime::None, - }, - MappedLocalTime::Ambiguous(o1, o2) => { - match (local.checked_sub_offset(o1.fix()), local.checked_sub_offset(o2.fix())) { - (Some(d1), Some(d2)) => MappedLocalTime::Ambiguous( - DateTime::from_naive_utc_and_offset(d1, o1), - DateTime::from_naive_utc_and_offset(d2, o2), - ), - _ => MappedLocalTime::None, - } - } - } + self.offset_from_local_datetime(local).try_map(|off| { + local + .checked_sub_offset(off.fix()) + .map(|dt| DateTime::from_naive_utc_and_offset(dt, off)) + }) } /// Creates the offset for given UTC `NaiveDate`. This cannot fail.