ako 0.0.3

Ako is a Rust crate that offers a practical and human-friendly approach to creating, manipulating, formatting and converting dates, times and timestamps.
Documentation
use alloc::sync::Arc;

use crate::time_zone::location::Location;
use crate::{Moment, Offset};

mod location;

/// A **time zone**, such as `Europe/Paris`.
///
/// A time zone is a collection of rules that maps **moments** on the time-line from “exact time” (timestamps)
/// to civilian (civil) time (a date on a calendar and a time on the clock).
///
#[derive(Clone)]
pub struct TimeZone {
    kind: TimeZoneKind,
}

#[derive(Clone)]
enum TimeZoneKind {
    // The default system time zone.
    // Loaded on first use and statically cached.
    // TODO: System,

    // A time zone for a geographic location, such as `Europe/Paris`.
    Location(Arc<Location>),

    // A fixed offset.
    Fixed(Offset),
}

// Constants
impl TimeZone {
    /// The time zone for [Coordinated Universal Time] (UTC).
    ///
    /// This canonically has an offset of zero seconds and never changes.
    ///
    /// [Coordinated Universal Time]: https://en.wikipedia.org/wiki/Coordinated_Universal_Time
    ///
    pub const UTC: Self = Self::fixed(Offset::UTC);
}

// Construction
impl TimeZone {
    /// Returns the [`TimeZone`] for a geographic _location_, with the
    /// given [time zone identifier], such as `America/New_York`.
    ///
    /// [time zone identifier]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
    ///
    pub fn location(id: &str) -> crate::Result<Self> {
        let location = Location::of(id)?;

        Ok(Self {
            kind: TimeZoneKind::Location(Arc::new(location)),
        })
    }

    /// Returns a [`TimeZone`] that always uses the given offset.
    ///
    #[must_use]
    pub const fn fixed(offset: Offset) -> Self {
        Self {
            kind: TimeZoneKind::Fixed(offset),
        }
    }
}

// Components
impl TimeZone {
    /// Gets the canonical identifier for this time zone.
    ///
    pub fn id(&self) -> &'_ str {
        todo!()
    }
}

// Queries
impl TimeZone {
    /// Returns the offset in effect at the given `moment`.
    ///
    pub fn offset_at_moment(&self, moment: Moment) -> Offset {
        let secs = moment.to_unix_seconds();

        match &self.kind {
            // TODO: TimeZoneKind::System => SYSTEM.offset_at_utc_seconds(secs),
            TimeZoneKind::Location(location) => location.offset_at_utc_seconds(secs),
            TimeZoneKind::Fixed(offset) => offset.clone(),
        }
    }
}