import pytest
from astrora._core import Duration, Epoch
class TestEpochCreation:
def test_epoch_from_gregorian_utc(self):
epoch = Epoch(2000, 1, 1, 12, 0, 0, 0)
assert epoch is not None
def test_epoch_with_default_params(self):
epoch = Epoch(2024, 10, 22) assert epoch is not None
def test_j2000_epoch(self):
j2000 = Epoch.j2000_epoch()
assert abs(j2000.mjd_tt - 51544.5) < 1e-6
assert abs(j2000.jd_tt - 2451545.0) < 1e-6
assert abs(j2000.tt_seconds) < 1e-6
def test_midnight_and_noon_constructors(self):
midnight = Epoch.from_midnight_utc(2000, 1, 1)
noon = Epoch.from_noon_utc(2000, 1, 1)
diff = noon - midnight
assert abs(diff.hours - 12.0) < 1e-6
class TestTimeScaleConversions:
def test_utc_to_tai_conversion(self):
utc_epoch = Epoch(2020, 3, 15, 10, 30, 45, 0)
tai_epoch = utc_epoch.as_tai()
diff = tai_epoch - utc_epoch
assert abs(diff.seconds) < 1e-3
def test_utc_to_tt_conversion(self):
utc_epoch = Epoch(2020, 3, 15, 10, 30, 45, 0)
tt_epoch = utc_epoch.as_tt()
diff = tt_epoch - utc_epoch
assert abs(diff.seconds) < 1e-3
def test_utc_to_tdb_conversion(self):
utc_epoch = Epoch(2020, 3, 15, 10, 30, 45, 0)
tdb_epoch = utc_epoch.as_tdb()
diff = tdb_epoch - utc_epoch
assert abs(diff.seconds) < 1e-3
def test_mjd_in_different_scales(self):
epoch = Epoch(2000, 1, 1, 0, 0, 0, 0)
mjd_utc = epoch.mjd_utc
mjd_tai = epoch.mjd_tai
mjd_tt = epoch.mjd_tt
assert abs(mjd_tai - mjd_utc) > 0.0003 assert abs(mjd_tai - mjd_utc) < 0.0005
assert abs(mjd_tt - mjd_tai) > 0.00037 assert abs(mjd_tt - mjd_tai) < 0.00038
class TestMJDJDConversions:
def test_mjd_jd_relationship(self):
epoch = Epoch(2000, 1, 1, 0, 0, 0, 0)
mjd = epoch.mjd_utc
jd = epoch.jd_utc
assert abs(jd - (mjd + 2400000.5)) < 1e-9
def test_mjd_value_at_j2000(self):
epoch = Epoch(2000, 1, 1, 0, 0, 0, 0)
assert abs(epoch.mjd_utc - 51544.0) < 0.001
class TestDurationOperations:
def test_duration_from_seconds(self):
dur = Duration(3600.0) assert abs(dur.seconds - 3600.0) < 1e-9
assert abs(dur.minutes - 60.0) < 1e-9
assert abs(dur.hours - 1.0) < 1e-9
def test_duration_from_minutes(self):
dur = Duration.from_min(90.0) assert abs(dur.minutes - 90.0) < 1e-9
assert abs(dur.hours - 1.5) < 1e-9
assert abs(dur.seconds - 5400.0) < 1e-9
def test_duration_from_hours(self):
dur = Duration.from_hrs(2.5)
assert abs(dur.hours - 2.5) < 1e-9
assert abs(dur.minutes - 150.0) < 1e-9
def test_duration_from_days(self):
dur = Duration.from_day(1.5)
assert abs(dur.days - 1.5) < 1e-9
assert abs(dur.hours - 36.0) < 1e-9
def test_duration_addition(self):
d1 = Duration.from_hrs(1.0)
d2 = Duration.from_min(30.0)
sum_dur = d1 + d2
assert abs(sum_dur.minutes - 90.0) < 1e-9
def test_duration_subtraction(self):
d1 = Duration.from_hrs(2.0)
d2 = Duration.from_min(30.0)
diff_dur = d1 - d2
assert abs(diff_dur.minutes - 90.0) < 1e-9
def test_duration_multiplication(self):
dur = Duration.from_hrs(1.0)
scaled = dur * 2.5
assert abs(scaled.hours - 2.5) < 1e-9
def test_duration_division(self):
dur = Duration.from_hrs(3.0)
divided = dur / 2.0
assert abs(divided.hours - 1.5) < 1e-9
def test_duration_negation(self):
dur = Duration.from_hrs(1.0)
neg_dur = -dur
assert abs(neg_dur.hours + 1.0) < 1e-9
def test_duration_abs(self):
dur = Duration.from_hrs(-2.5)
abs_dur = abs(dur)
assert abs(abs_dur.hours - 2.5) < 1e-9
class TestEpochDurationArithmetic:
def test_epoch_plus_duration(self):
epoch = Epoch.j2000_epoch()
duration = Duration.from_day(1.0)
future = epoch + duration
diff = future - epoch
assert abs(diff.days - 1.0) < 1e-9
def test_epoch_minus_duration(self):
epoch = Epoch.j2000_epoch()
duration = Duration.from_day(1.0)
past = epoch - duration
diff = epoch - past
assert abs(diff.days - 1.0) < 1e-9
def test_epoch_difference(self):
epoch1 = Epoch.j2000_epoch()
epoch2 = Epoch(2000, 1, 2, 12, 0, 0, 0)
diff = epoch2 - epoch1
assert abs(diff.days - 1.0) < 0.001
class TestEpochComparison:
def test_epoch_equality(self):
epoch1 = Epoch(2000, 1, 1, 12, 0, 0, 0)
epoch2 = Epoch(2000, 1, 1, 12, 0, 0, 0)
assert epoch1 == epoch2
def test_epoch_less_than(self):
epoch1 = Epoch.j2000_epoch()
epoch2 = epoch1 + Duration.from_day(1.0)
assert epoch1 < epoch2
def test_epoch_greater_than(self):
epoch1 = Epoch.j2000_epoch()
epoch2 = epoch1 - Duration.from_day(1.0)
assert epoch1 > epoch2
def test_epoch_less_equal(self):
epoch1 = Epoch.j2000_epoch()
epoch2 = epoch1 + Duration.from_day(1.0)
assert epoch1 <= epoch2
assert epoch1 <= epoch1
def test_epoch_greater_equal(self):
epoch1 = Epoch.j2000_epoch()
epoch2 = epoch1 - Duration.from_day(1.0)
assert epoch1 >= epoch2
assert epoch1 >= epoch1
class TestDurationComparison:
def test_duration_equality(self):
d1 = Duration.from_hrs(1.0)
d2 = Duration.from_min(60.0)
assert d1 == d2
def test_duration_less_than(self):
d1 = Duration.from_hrs(1.0)
d2 = Duration.from_hrs(2.0)
assert d1 < d2
def test_duration_greater_than(self):
d1 = Duration.from_hrs(2.0)
d2 = Duration.from_hrs(1.0)
assert d1 > d2
class TestStringRepresentation:
def test_epoch_repr(self):
epoch = Epoch.j2000_epoch()
repr_str = repr(epoch)
assert "Epoch" in repr_str
def test_epoch_str(self):
epoch = Epoch.j2000_epoch()
str_repr = str(epoch)
assert "2000" in str_repr
def test_duration_repr(self):
dur = Duration.from_hrs(1.5)
repr_str = repr(dur)
assert "Duration" in repr_str
def test_duration_str(self):
dur = Duration.from_day(2.5)
str_repr = str(dur)
assert "days" in str_repr or "s" in str_repr
class TestAstrodynamicsWorkflow:
def test_orbital_period_calculation(self):
epoch_start = Epoch.j2000_epoch()
orbital_period = Duration.from_min(92.0)
epoch_end = epoch_start + orbital_period
diff = epoch_end - epoch_start
assert abs(diff.minutes - 92.0) < 1e-6
def test_time_of_flight_calculation(self):
launch = Epoch(2024, 10, 22, 10, 0, 0, 0)
tof = Duration.from_day(210.0)
arrival = launch + tof
computed_tof = arrival - launch
assert abs(computed_tof.days - 210.0) < 1e-6
def test_propagation_timesteps(self):
t0 = Epoch.j2000_epoch()
dt = Duration(60.0)
epochs = [t0 + dt * i for i in range(10)]
for i in range(1, len(epochs)):
diff = epochs[i] - epochs[i - 1]
assert abs(diff.seconds - 60.0) < 1e-6
def test_mission_duration(self):
launch = Epoch(2024, 1, 1, 0, 0, 0, 0)
end = Epoch(2025, 1, 1, 0, 0, 0, 0)
mission_duration = end - launch
assert 364.9 < mission_duration.days < 366.1
if __name__ == "__main__":
pytest.main([__file__, "-v"])