diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/datetime.rs | 32 | ||||
| -rw-r--r-- | src/month.rs | 2 | ||||
| -rw-r--r-- | src/tai.rs | 6 | ||||
| -rw-r--r-- | src/timezone.rs | 8 |
4 files changed, 39 insertions, 9 deletions
diff --git a/src/datetime.rs b/src/datetime.rs index 9332de1..49506e3 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -30,6 +30,16 @@ impl<Tz: TimeZone> DateTime<Tz> { } } + pub fn from_local(local_datetime: NaiveDateTime, timezone: Tz) -> Result<Self, Tz::Err> { + let offset = timezone.offset_from_local_naive(local_datetime)?; + // TODO overflow + let utc_datetime = local_datetime + .add_seconds_overflowing(-offset.seconds_ahead() as i64) + .0; + + Ok(Self::from_utc(utc_datetime, timezone)) + } + pub fn offset(&self) -> UtcOffset { let utc = self.as_utc(); self.timezone.utc_offset(utc) @@ -69,6 +79,26 @@ impl<Tz: TimeZone> DateTime<Tz> { pub fn tai_timestamp(&self) -> UnixTimestamp { self.as_tai().to_naive_overflowing().0.timestamp() } + + #[must_use] + pub fn add_seconds_overflowing(self, seconds: i64) -> (Self, bool) { + let (tai_timestamp, overflow) = self.tai_timestamp().add_seconds_overflowing(seconds); + let tai_naive_dt = NaiveDateTime::from_timestamp(tai_timestamp); + let tai_dt = DateTime::from_local(tai_naive_dt, Tai).unwrap(); + + (tai_dt.into_timezone(self.timezone), overflow) + } + + #[must_use] + pub fn add_nanoseconds_overflowing(self, nanoseconds: i64) -> (Self, bool) { + let (tai_timestamp, overflow) = self + .tai_timestamp() + .add_nanoseconds_overflowing(nanoseconds); + let tai_naive_dt = NaiveDateTime::from_timestamp(tai_timestamp); + let tai_dt = DateTime::from_local(tai_naive_dt, Tai).unwrap(); + + (tai_dt.into_timezone(self.timezone), overflow) + } } impl NaiveDateTime { @@ -285,7 +315,7 @@ impl<Tz: TimeZone, Other: TimeZone> PartialEq<DateTime<Other>> for DateTime<Tz> } impl<Tz: TimeZone> Hash for DateTime<Tz> { - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + fn hash<H: core::hash::Hasher>(&self, state: &mut H) { self.utc_datetime.hash(state); } } diff --git a/src/month.rs b/src/month.rs index 1419717..faf891d 100644 --- a/src/month.rs +++ b/src/month.rs @@ -405,7 +405,7 @@ impl Month { let zero_indexed_month = zero_indexed_num % 12; let month = match Self::from_u8((zero_indexed_month as u8) + 1) { Some(month) => month, - None => unsafe { std::hint::unreachable_unchecked() }, + None => unsafe { core::hint::unreachable_unchecked() }, }; (month, wraps) @@ -83,7 +83,7 @@ impl TimeZone for Tai { } // TODO optimize - fn offset_from_local_time(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err> { + fn offset_from_local_naive(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err> { // TAI times cannot have leap seconds if date_time.second() == 60 { return Err(UnexpectedLeapSecond { @@ -120,7 +120,7 @@ mod tests { #[test] fn test_conversion_no_leap_seconds() { let offset = unsafe { - Tai.offset_from_local_time(NaiveDateTime::new( + Tai.offset_from_local_naive(NaiveDateTime::new( Date::from_ymd_unchecked(2000.into(), Month::January, 1), Time::from_hms_unchecked(0, 0, 0), )) @@ -134,7 +134,7 @@ mod tests { fn test_conversion_one_leap_second() { add_leap_second(unsafe { Date::from_ymd_unchecked(2000.into(), Month::January, 1) }); let offset = unsafe { - Tai.offset_from_local_time(NaiveDateTime::new( + Tai.offset_from_local_naive(NaiveDateTime::new( Date::from_ymd_unchecked(2000.into(), Month::January, 2), Time::from_hms_unchecked(0, 0, 0), )) diff --git a/src/timezone.rs b/src/timezone.rs index f0096c6..eb539fb 100644 --- a/src/timezone.rs +++ b/src/timezone.rs @@ -5,7 +5,7 @@ use core::fmt::Display; /// A type that can be used to represent a `TimeZone` pub trait TimeZone: Sized + Eq + Display { /// The error to return in case of a failure to convert the local time to UTC - type Err; + type Err: core::fmt::Debug; /// Given the time in the UTC timezone, determine the `UtcOffset` fn utc_offset(&self, date_time: DateTime<Utc>) -> UtcOffset; @@ -16,7 +16,7 @@ pub trait TimeZone: Sized + Eq + Display { /// /// This returns an Err if the given `NaiveDateTime` cannot exist in this timezone. /// For example, the time may have been skipped because of daylight savings time. - fn offset_from_local_time(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err>; + fn offset_from_local_naive(&self, date_time: NaiveDateTime) -> Result<UtcOffset, Self::Err>; } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] @@ -30,7 +30,7 @@ impl TimeZone for Utc { UtcOffset::UTC } - fn offset_from_local_time(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> { + fn offset_from_local_naive(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> { Ok(UtcOffset::UTC) } } @@ -121,7 +121,7 @@ impl TimeZone for UtcOffset { *self } - fn offset_from_local_time(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> { + fn offset_from_local_naive(&self, _: NaiveDateTime) -> Result<UtcOffset, Self::Err> { Ok(*self) } } |
