use crate::astronomical::lunar_month::LunarMonth;
use crate::calendar::{days_between, validate_solar_date};
use crate::julian_day::to_solar_date;
use crate::normalize::normalize_lunar_date;
use crate::{LunarDate, LunarError, SolarDate};
pub fn solar_to_lunar(date: SolarDate) -> Result<LunarDate, LunarError> {
validate_solar_date(date)?;
let mut month = LunarMonth::from_ym(date.year, date.month as i8)?;
let mut offset = days_between(month.first_solar_date()?, date)?;
while offset < 0 {
month = month.next(-1)?;
offset += month.day_count()? as i32;
}
Ok(LunarDate {
year: month.year(),
month: month.month(),
day: (offset + 1) as u8,
is_leap_month: month.is_leap(),
})
}
pub fn lunar_to_solar(date: LunarDate) -> Result<SolarDate, LunarError> {
let date = normalize_lunar_date(date)?;
let month_with_leap = if date.is_leap_month {
-(date.month as i8)
} else {
date.month as i8
};
let month = LunarMonth::from_ym(date.year, month_with_leap)?;
let solar = to_solar_date(month.first_julian_day()? + date.day as f64 - 1.0);
validate_solar_date(solar)?;
Ok(solar)
}