use crate::NaiveDateTime; use core::convert::Infallible; /// A type that can be used to represent a TimeZone pub trait TimeZone { type Err; fn utc_offset(&self, date_time: NaiveDateTime) -> Result; } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] /// The UTC time zone pub struct Utc; impl TimeZone for Utc { type Err = Infallible; fn utc_offset(&self, _: NaiveDateTime) -> Result { Ok(UtcOffset::UTC) } } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] /// A timezone with a fixed offset from UTC pub struct UtcOffset { offset_seconds: i32, } impl UtcOffset { /// The UTC Timezone, represented as an offset pub const UTC: Self = Self { offset_seconds: 0 }; // TODO validation /// Makes a new `UtcOffset` timezone with the given timezone difference. /// A positive number is the Eastern hemisphere. A negative number is the /// Western hemisphere. /// /// # Safety /// /// A value with an absolute value greater than or equal to 86,400 results /// in undefined behavior pub const unsafe fn from_seconds_unchecked(seconds: i32) -> Self { Self { offset_seconds: seconds, } } /// Makes a new `UtcOffset` timezone with the given timezone difference. /// A positive number is the Eastern hemisphere. A negative number is the /// Western hemisphere. /// /// # Safety /// /// A value with an absolute value greater than or equal to 24 results /// in undefined behavior pub const unsafe fn from_hours_unchecked(hours: i8) -> Self { Self::from_seconds_unchecked(hours as i32 * 3600) } /// The number of hours this timezone is ahead of UTC. THis number is /// negative if the timezone is in the Western hemisphere pub fn hours_ahead(self) -> f32 { self.offset_seconds as f32 / 3600.0 } /// The number of seconds this timezone is ahead of UTC. This number is /// negative if the timezone is in the Western hemisphere pub const fn seconds_ahead(self) -> i32 { self.offset_seconds } } impl TimeZone for UtcOffset { type Err = Infallible; fn utc_offset(&self, _: NaiveDateTime) -> Result { Ok(*self) } }