use super::{Zodiac, BA_ZI_WEIGHT_TIME, THE_EARTHLY_BRANCHES, THE_EARTHLY_BRANCHES_CHARS};
use std::mem::transmute;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use chrono::prelude::*;
#[derive(Debug, PartialOrd, Ord, PartialEq, Clone, Eq, Hash, Copy)]
pub enum EarthlyBranch {
First,
Second,
Third,
Fourth,
Fifth,
Sixth,
Seventh,
Eighth,
Ninth,
Tenth,
Eleventh,
Twelfth,
}
impl EarthlyBranch {
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn from_ordinal_unsafe(number: i8) -> EarthlyBranch {
transmute(number)
}
#[inline]
pub fn from_time<T: Timelike>(time: T) -> EarthlyBranch {
let hour = time.hour();
let ordinal = ((hour + 1) % 24) / 2;
unsafe { Self::from_ordinal_unsafe(ordinal as i8) }
}
#[allow(clippy::should_implement_trait)]
#[inline]
pub fn from_str<S: AsRef<str>>(s: S) -> Option<EarthlyBranch> {
let s = s.as_ref();
for (i, &t) in THE_EARTHLY_BRANCHES.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_EARTHLY_BRANCHES[i]
}
#[inline]
pub fn from_char(c: char) -> Option<EarthlyBranch> {
for (i, t) in THE_EARTHLY_BRANCHES_CHARS.iter().copied().enumerate() {
if t == c {
return Some(unsafe { Self::from_ordinal_unsafe(i as i8) });
}
}
None
}
#[inline]
pub fn to_char(self) -> char {
let i = self as usize;
THE_EARTHLY_BRANCHES_CHARS[i]
}
#[inline]
pub fn from_zodiac(zodiac: Zodiac) -> EarthlyBranch {
unsafe { transmute(zodiac) }
}
#[inline]
pub fn to_zodiac(self) -> Zodiac {
unsafe { transmute(self) }
}
#[inline]
pub fn get_ba_zi_weight(self) -> u8 {
let i = self as usize;
BA_ZI_WEIGHT_TIME[i]
}
}
impl Display for EarthlyBranch {
#[inline]
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str(self.to_str())
}
}
impl From<Zodiac> for EarthlyBranch {
#[inline]
fn from(zodiac: Zodiac) -> EarthlyBranch {
EarthlyBranch::from_zodiac(zodiac)
}
}
impl FromStr for EarthlyBranch {
type Err = ();
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
EarthlyBranch::from_str(s).ok_or(())
}
}