use crate::time::JulianDate;
use qtty::*;
use std::f64::consts::TAU;
#[inline]
pub fn earth_rotation_angle(jd_ut1: JulianDate) -> Radians {
let du = (jd_ut1 - JulianDate::J2000).value();
let frac = du.fract();
let era = TAU * (0.779_057_273_264_0 + 0.002_737_811_911_354_48 * du + frac);
Radians::new(era.rem_euclid(TAU))
}
#[inline]
pub fn equation_of_the_origins(
psib_plus_dpsi: Radians,
epsa_plus_deps: Radians,
cio_locator_s: Radians,
) -> Radians {
Radians::new(-(psib_plus_dpsi.value()) * epsa_plus_deps.cos() - cio_locator_s.value())
}
#[inline]
pub fn equation_of_the_equinoxes(dpsi: Radians, true_obliquity: Radians) -> Radians {
Radians::new(dpsi.value() * true_obliquity.cos())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn era_at_j2000() {
let era = earth_rotation_angle(JulianDate::J2000);
let era_deg = era.to::<Degree>();
assert!(
(era_deg.value() - 280.46_f64).abs() < 0.1,
"ERA at J2000 = {}°, expected ≈ 280.46°",
era_deg
);
}
#[test]
fn era_increases_with_time() {
let era1 = earth_rotation_angle(JulianDate::new(2_451_545.0));
let era2 = earth_rotation_angle(JulianDate::new(2_451_545.5));
let diff = ((era2 - era1).value()).rem_euclid(TAU);
let diff_deg = diff.to_degrees();
assert!(
(diff_deg - 180.49).abs() < 1.0,
"ERA increase over 0.5 days = {}°, expected ≈ 180.5°",
diff_deg
);
}
#[test]
fn era_range() {
for jd in [2_451_545.0, 2_460_000.5, 2_440_000.0] {
let era = earth_rotation_angle(JulianDate::new(jd));
assert!(era >= Radians::new(0.0), "ERA should be ≥ 0");
assert!(era < Radians::new(TAU), "ERA should be < 2π");
}
}
}