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 core::fmt::{self, Debug, Formatter};

use crate::calendar::Iso;
use crate::{Calendar, YearMonth};

/// A **month** on a calendar.
///
/// This type does not store or represent a year, day, time, or time-zone.
///
/// It is not possible to know the number of days in the month from this type
/// as that may change based on the year.
///
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Month<C: Calendar = Iso> {
    calendar: C,
    number: u8,
}

// Constructor
impl<C: Calendar> Month<C> {
    /// Obtains a month from the number of the year on the given calendar, without any checks.
    #[allow(unsafe_code)]
    #[must_use]
    pub(crate) const unsafe fn unchecked_of(calendar: C, number: u8) -> Self {
        Self { calendar, number }
    }
}

// Components
impl<C: Calendar> Month<C> {
    /// Gets the calendar that this month is interpreted in.
    #[must_use]
    pub const fn calendar(self) -> C {
        self.calendar
    }

    /// Gets the month-of-year number, starting from `1`.
    #[must_use]
    pub const fn number(self) -> u8 {
        self.number
    }

    // TODO: name()
}

// Composition
impl<C: Calendar> Month<C> {
    /// Combines this month with the given year to create a [`YearMonth`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use ako::calendar::Iso;
    /// # fn main() -> ako::Result<()> {
    /// let days_in_feb = Iso::FEBRUARY.with_year(2024)?.days();
    ///
    /// assert_eq!(days_in_feb, 29);
    /// # Ok(()) }
    /// ```
    ///
    pub fn with_year(self, year: i32) -> crate::Result<YearMonth<C>> {
        YearMonth::of(self.calendar, year, self.number)
    }
}

// TODO: with_day

impl<C: Calendar> Debug for Month<C> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.pad(&self.format_rfc3339())
    }
}