use icu_calendar::{AsCalendar, Date, RangeError};
macro_rules! dt_unit {
($name:ident, $storage:ident, $value:expr, $(#[$docs:meta])+) => {
$(#[$docs])+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct $name($storage);
impl $name {
pub const fn number(self) -> $storage {
self.0
}
pub const fn zero() -> $name {
Self(0)
}
#[inline]
pub fn is_zero(self) -> bool {
self.0 == 0
}
}
impl TryFrom<$storage> for $name {
type Error = RangeError;
fn try_from(input: $storage) -> Result<Self, Self::Error> {
if input > $value {
Err(RangeError {
field: stringify!($name),
min: 0,
max: $value,
value: input as i32,
})
} else {
Ok(Self(input))
}
}
}
impl TryFrom<usize> for $name {
type Error = RangeError;
fn try_from(input: usize) -> Result<Self, Self::Error> {
if input > $value {
Err(RangeError {
field: "$name",
min: 0,
max: $value,
value: input as i32,
})
} else {
Ok(Self(input as $storage))
}
}
}
impl From<$name> for $storage {
fn from(input: $name) -> Self {
input.0
}
}
impl From<$name> for usize {
fn from(input: $name) -> Self {
input.0 as Self
}
}
};
}
dt_unit!(
Hour,
u8,
23,
);
dt_unit!(
Minute,
u8,
59,
);
dt_unit!(
Second,
u8,
60,
);
dt_unit!(
Nanosecond,
u32,
999_999_999,
);
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[allow(clippy::exhaustive_structs)] pub struct Time {
pub hour: Hour,
pub minute: Minute,
pub second: Second,
pub subsecond: Nanosecond,
}
impl Time {
pub const fn new(hour: Hour, minute: Minute, second: Second, subsecond: Nanosecond) -> Self {
Self {
hour,
minute,
second,
subsecond,
}
}
pub const fn midnight() -> Self {
Self {
hour: Hour::zero(),
minute: Minute::zero(),
second: Second::zero(),
subsecond: Nanosecond::zero(),
}
}
pub fn try_new(hour: u8, minute: u8, second: u8, nanosecond: u32) -> Result<Self, RangeError> {
Ok(Self {
hour: hour.try_into()?,
minute: minute.try_into()?,
second: second.try_into()?,
subsecond: nanosecond.try_into()?,
})
}
}
#[derive(Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_structs)] pub struct DateTime<A: AsCalendar> {
pub date: Date<A>,
pub time: Time,
}
#[derive(Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_structs)] pub struct ZonedDateTime<A: AsCalendar, Z> {
pub date: Date<A>,
pub time: Time,
pub zone: Z,
}