from __future__ import annotations from datetime import datetime, timezone import numpy as np from tools.export_g90_rtk_to_sessions import nmea_utc_to_unix_s from tools.time_alignment import fit_affine_clock def test_fit_affine_clock_large_epoch_and_receive_spike() -> None: device = np.linspace(10_000.0, 10_300.0, 601) host = 1_786_000_000.0 + 1.00002 * (device - device[0]) host[250] += 0.25 model = fit_affine_clock(device, host) assert abs(model.scale - 1.00002) < 1e-7 assert abs(model.map(device[400]) - host[400]) < 1e-4 assert model.inlier_count < model.sample_count assert abs(model.inverse(model.map(device[123])) - device[123]) < 1e-7 def test_nmea_utc_uses_measurement_time_not_receive_time() -> None: receive = datetime(2026, 8, 14, 11, 34, 12, tzinfo=timezone.utc).timestamp() measurement = nmea_utc_to_unix_s("113408.85", receive) assert abs((receive - measurement) - 3.15) < 1e-6 def test_nmea_utc_resolves_midnight_rollover() -> None: receive = datetime(2026, 8, 15, 0, 0, 1, tzinfo=timezone.utc).timestamp() measurement = nmea_utc_to_unix_s("235959.50", receive) assert abs((receive - measurement) - 1.5) < 1e-6