From 86cd77754a1fbd49a6f1e9357736d6cff69dea1a Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Fri, 19 May 2023 18:48:46 +0200 Subject: [PATCH] Use `NaiveDateTime::and_local_timezone` in `TimeZone::from_local_datetime` --- src/naive/datetime/mod.rs | 8 ++++++++ src/offset/mod.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index 0ea6f24153..4cdeb60b3e 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -948,6 +948,14 @@ impl NaiveDateTime { /// ``` #[must_use] pub fn and_local_timezone(&self, tz: Tz) -> LocalResult> { + self.and_local_timezone_internal(&tz) + } + + // FIXME: ideally tz should be taken by reference, but that would be a breaking change. + pub(crate) fn and_local_timezone_internal( + &self, + tz: &Tz, + ) -> LocalResult> { let local_result_offset = tz.offset_from_local_datetime(self); local_time_min_offset(local_result_offset, self).unwrap_or(LocalResult::None) } diff --git a/src/offset/mod.rs b/src/offset/mod.rs index ea53915309..64479f5321 100644 --- a/src/offset/mod.rs +++ b/src/offset/mod.rs @@ -473,8 +473,7 @@ 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) -> LocalResult> { - self.offset_from_local_datetime(local) - .map(|offset| DateTime::from_naive_utc_and_offset(*local - offset.fix(), offset)) + local.and_local_timezone_internal(self) } /// Creates the offset for given UTC `NaiveDate`. This cannot fail. @@ -504,6 +503,32 @@ pub trait TimeZone: Sized + Clone { mod tests { use super::*; + #[test] + fn test_fixed_offset_min_max_dates() { + for offset_hour in -23..=23 { + dbg!(offset_hour); + let offset = FixedOffset::east_opt(offset_hour * 60 * 60).unwrap(); + + let local_max = offset.from_utc_datetime(&NaiveDateTime::MAX); + assert_eq!(local_max.naive_utc(), NaiveDateTime::MAX); + let local_min = offset.from_utc_datetime(&NaiveDateTime::MIN); + assert_eq!(local_min.naive_utc(), NaiveDateTime::MIN); + + let local_max = offset.from_local_datetime(&NaiveDateTime::MAX); + if offset_hour >= 0 { + assert_eq!(local_max.unwrap().naive_local(), NaiveDateTime::MAX); + } else { + assert_eq!(local_max, LocalResult::None); + } + let local_min = offset.from_local_datetime(&NaiveDateTime::MIN); + if offset_hour <= 0 { + assert_eq!(local_min.unwrap().naive_local(), NaiveDateTime::MIN); + } else { + assert_eq!(local_min, LocalResult::None); + } + } + } + #[test] fn test_negative_millis() { let dt = Utc.timestamp_millis_opt(-1000).unwrap();