use super::{SolarYear, THE_SOLAR_MONTHS};
use std::mem::transmute;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
#[derive(Debug, PartialOrd, Ord, PartialEq, Clone, Eq, Hash, Copy)]
pub enum SolarMonth {
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December,
}
impl SolarMonth {
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn from_ordinal_unsafe(number: i8) -> SolarMonth {
transmute(number)
}
#[allow(clippy::should_implement_trait)]
#[inline]
pub fn from_str<S: AsRef<str>>(s: S) -> Option<SolarMonth> {
let s = s.as_ref();
for (i, &t) in THE_SOLAR_MONTHS.iter().enumerate() {
if t == s {
return Some(unsafe { Self::from_ordinal_unsafe(i as i8) });
}
}
None
}
#[inline]
pub fn to_str(self) -> &'static str {
let i = self as usize;
THE_SOLAR_MONTHS[i]
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn from_u8_unsafe(month: u8) -> SolarMonth {
transmute(month - 1)
}
#[inline]
pub fn from_u8(month: u8) -> Option<SolarMonth> {
if month == 0 || month > 12 {
None
} else {
Some(unsafe { Self::from_u8_unsafe(month) })
}
}
#[inline]
pub fn to_u8(self) -> u8 {
let i = self as u8;
i + 1
}
#[inline]
pub fn get_total_days<Y: Into<SolarYear>>(self, solar_year: Y) -> u8 {
let month = self.to_u8();
let m = u8::from(month < 8);
if month % 2 == m {
31
} else if month == 2 {
if solar_year.into().is_leap() {
29
} else {
28
}
} else {
30
}
}
}
impl Display for SolarMonth {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str(self.to_str())
}
}
impl FromStr for SolarMonth {
type Err = ();
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
SolarMonth::from_str(s).ok_or(())
}
}