use core::fmt;
use crate::{scaffold::IntoOption, TimeZoneBcp47Id, UtcOffset, ZoneVariant};
use icu_calendar::{Date, Iso, Time};
mod private {
pub trait Sealed {}
}
pub trait TimeZoneModel: private::Sealed {
type ZoneVariant: IntoOption<ZoneVariant> + fmt::Debug + Copy;
type LocalTime: IntoOption<(Date<Iso>, Time)> + fmt::Debug + Copy;
}
pub mod models {
use super::*;
#[derive(Debug)]
#[non_exhaustive]
pub enum Base {}
impl super::private::Sealed for Base {}
impl TimeZoneModel for Base {
type ZoneVariant = ();
type LocalTime = ();
}
#[derive(Debug)]
#[non_exhaustive]
pub enum AtTime {}
impl super::private::Sealed for AtTime {}
impl TimeZoneModel for AtTime {
type ZoneVariant = ();
type LocalTime = (Date<Iso>, Time);
}
#[derive(Debug)]
#[non_exhaustive]
pub enum Full {}
impl super::private::Sealed for Full {}
impl TimeZoneModel for Full {
type ZoneVariant = ZoneVariant;
type LocalTime = (Date<Iso>, Time);
}
}
#[derive(Debug, PartialEq, Eq)]
#[allow(clippy::exhaustive_structs)] pub struct TimeZoneInfo<Model: TimeZoneModel> {
time_zone_id: TimeZoneBcp47Id,
offset: Option<UtcOffset>,
local_time: Model::LocalTime,
zone_variant: Model::ZoneVariant,
}
impl<Model: TimeZoneModel> Clone for TimeZoneInfo<Model> {
fn clone(&self) -> Self {
*self
}
}
impl<Model: TimeZoneModel> Copy for TimeZoneInfo<Model> {}
impl<Model: TimeZoneModel> TimeZoneInfo<Model> {
pub fn time_zone_id(self) -> TimeZoneBcp47Id {
self.time_zone_id
}
pub fn offset(self) -> Option<UtcOffset> {
self.offset
}
}
impl<Model> TimeZoneInfo<Model>
where
Model: TimeZoneModel<LocalTime = (Date<Iso>, Time)>,
{
pub fn local_time(self) -> (Date<Iso>, Time) {
self.local_time
}
}
impl<Model> TimeZoneInfo<Model>
where
Model: TimeZoneModel<ZoneVariant = ZoneVariant>,
{
pub fn zone_variant(self) -> ZoneVariant {
self.zone_variant
}
}
impl TimeZoneBcp47Id {
pub const fn with_offset(self, offset: Option<UtcOffset>) -> TimeZoneInfo<models::Base> {
TimeZoneInfo {
offset,
time_zone_id: self,
local_time: (),
zone_variant: (),
}
}
pub const fn without_offset(self) -> TimeZoneInfo<models::Base> {
TimeZoneInfo {
offset: None,
time_zone_id: self,
local_time: (),
zone_variant: (),
}
}
}
impl TimeZoneInfo<models::Base> {
pub const fn unknown() -> Self {
TimeZoneBcp47Id::unknown().with_offset(None)
}
pub const fn utc() -> Self {
TimeZoneBcp47Id(tinystr::tinystr!(8, "utc")).with_offset(Some(UtcOffset::zero()))
}
pub const fn at_time(self, local_time: (Date<Iso>, Time)) -> TimeZoneInfo<models::AtTime> {
TimeZoneInfo {
offset: self.offset,
time_zone_id: self.time_zone_id,
local_time,
zone_variant: (),
}
}
}
impl TimeZoneInfo<models::AtTime> {
pub const fn with_zone_variant(self, zone_variant: ZoneVariant) -> TimeZoneInfo<models::Full> {
TimeZoneInfo {
offset: self.offset,
time_zone_id: self.time_zone_id,
local_time: self.local_time,
zone_variant,
}
}
}