refactor: code deduplication, extracted conversion into utils module

This commit is contained in:
YK 2024-12-07 06:37:36 +03:00
parent c4045c9142
commit 3913e79acf

View File

@ -13,48 +13,36 @@ pub struct NaiveJulianDate {
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct JulianDayNumber (u32);
impl From<NaiveDate> for JulianDayNumber {
fn from (value: NaiveDate) -> Self {
pub struct JulianDayNumberUtils;
impl JulianDayNumberUtils {
/// Given a month, day, and year, converts them into a julian day number (first return tuple member)
/// Second tuple member -- value of g that is required to calculate additional subtrahend for J for gregorian dates
pub fn julian_into_julian_day_number (day: i32, month: i32, year: i32) -> (i32, i32) {
use tables::julian_gregorian::*;
let D = value.day();
let M = value.month();
let Y = value.year();
let h = M as i32 - m;
let g = Y as i32 + y - (n - h) / n;
let h = month - m;
let g = year + y - (n - h) / n;
let f = (h - 1 + n) % n;
let e = (p * g + q) / r + D as i32 - 1 - j;
let e = (p * g + q) / r + day - 1 - j;
let J = e + (s * f + t) / u;
let J = J - (3 * ((g + A) / 100)) / 4 - C;
Self(J as u32)
(e + (s * f + t) / u, g)
}
}
impl From<NaiveJulianDate> for JulianDayNumber {
fn from (NaiveJulianDate { day: D, year: Y, month: M }: NaiveJulianDate) -> Self {
pub fn gregorian_into_julian_day_number (day: i32, month: i32, year: i32) -> i32 {
use tables::julian_gregorian::*;
let (J, g) = Self::julian_into_julian_day_number(day, month, year);
J - (3 * ((g + A) / 100)) / 4 - C
}
/// Converts Julian Day Number into a generic year-month-day tuple.
/// For gregorian dates, `f_extra` must be calculated with `JulianDayNumberUtils::gregorian_f_extra_for_julian_day`.
/// For julian dates, f_extra must be 0.
pub fn julian_day_number_into_ymd (julian_day: i32, f_extra: i32) -> (i32, u32, u32) {
use tables::julian_gregorian::*;
let h = M as i32 - m;
let g = Y as i32 + y - (n - h) / n;
let f = (h - 1 + n) % n;
let e = (p * g + q) / r + D as i32 - 1 - j;
let J = e + (s * f + t) / u;
Self(J as u32)
}
}
impl From<JulianDayNumber> for NaiveJulianDate {
fn from (JulianDayNumber(J): JulianDayNumber) -> Self {
use tables::julian_gregorian::*;
let f = J as i32 + j;
let f = julian_day + j + f_extra;
let e = r * f + v;
let g = e % p / r;
let h = u * g + w;
@ -63,6 +51,33 @@ impl From<JulianDayNumber> for NaiveJulianDate {
let month = ((h / s + m) % n + 1) as u32;
let year = e / p - y + (n + m - month as i32) / n;
(year, month, day)
}
/// Returns extra `f` addend for calculating Gregorian calendar date from Julian Day Number
pub fn gregorian_f_extra_for_julian_day (julian_day: i32) -> i32 {
use tables::julian_gregorian::*;
(((julian_day * 4 + B) / 146_097) * 3) / 4 + C
}
}
impl From<NaiveDate> for JulianDayNumber {
fn from (value: NaiveDate) -> Self {
let D = value.day(); let M = value.month(); let Y = value.year();
let J = JulianDayNumberUtils::gregorian_into_julian_day_number(D as i32, M as i32, Y);
Self(J as u32)
}
}
impl From<NaiveJulianDate> for JulianDayNumber {
fn from (NaiveJulianDate { day: D, year: Y, month: M }: NaiveJulianDate) -> Self {
Self(JulianDayNumberUtils::julian_into_julian_day_number(D as i32, M as i32, Y).0 as u32)
}
}
impl From<JulianDayNumber> for NaiveJulianDate {
fn from (JulianDayNumber(jd): JulianDayNumber) -> Self {
let (year, month, day) = JulianDayNumberUtils::julian_day_number_into_ymd(jd as i32, 0);
Self { year, day, month }
}
}
@ -70,17 +85,8 @@ impl From<JulianDayNumber> for NaiveJulianDate {
impl TryFrom<JulianDayNumber> for NaiveDate {
type Error = ConversionError;
fn try_from (JulianDayNumber(J): JulianDayNumber) -> Result<Self, Self::Error> {
use tables::julian_gregorian::*;
let f = J as i32 + j + (((J as i32 * 4 + B) / 146_097) * 3) / 4 + C;
let e = r * f + v;
let g = e % p / r;
let h = u * g + w;
let day = (h % s / u + 1) as u32;
let month = ((h / s + m) % n + 1) as u32;
let year = e / p - y + (n + m - month as i32) / n;
fn try_from (JulianDayNumber(jd): JulianDayNumber) -> Result<Self, Self::Error> {
let (year, month, day) = JulianDayNumberUtils::julian_day_number_into_ymd(jd as i32, JulianDayNumberUtils::gregorian_f_extra_for_julian_day(jd as i32));
Self::from_ymd_opt(year, month, day).ok_or_else(|| ConversionError::Generic)
}