Skip to main content

celestial_eop_data/
lib.rs

1mod decompress;
2mod entry;
3
4pub use entry::EopEntry;
5
6pub fn c04_data() -> &'static [EopEntry] {
7    decompress::c04()
8}
9
10pub fn finals_data() -> &'static [EopEntry] {
11    decompress::finals()
12}
13
14pub fn combined_data() -> Vec<EopEntry> {
15    let c04 = c04_data();
16    let finals = finals_data();
17    let c04_max_mjd = c04.last().map(|e| e.mjd).unwrap_or(0.0);
18    let mut combined = c04.to_vec();
19    combined.extend(finals.iter().filter(|e| e.mjd > c04_max_mjd));
20    combined
21}
22
23pub fn data_time_span() -> (f64, f64) {
24    let combined = combined_data();
25    let first = combined.first().map(|e| e.mjd).unwrap_or(0.0);
26    let last = combined.last().map(|e| e.mjd).unwrap_or(0.0);
27    (first, last)
28}
29
30pub fn data_timestamp() -> &'static str {
31    include_str!(concat!(env!("OUT_DIR"), "/eop_timestamp.txt"))
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn c04_loads_enough_records() {
40        assert!(c04_data().len() > 20_000);
41    }
42
43    #[test]
44    fn finals_loads_enough_records() {
45        assert!(finals_data().len() > 10_000);
46    }
47
48    #[test]
49    fn combined_sorted_no_duplicates() {
50        let data = combined_data();
51        for pair in data.windows(2) {
52            assert!(pair[1].mjd > pair[0].mjd, "not sorted at MJD {}", pair[0].mjd);
53        }
54    }
55
56    #[test]
57    fn time_span_covers_expected_range() {
58        let (start, end) = data_time_span();
59        assert!(start <= 37665.0, "start MJD {} too late", start);
60        assert!(end >= 60000.0, "end MJD {} too early", end);
61    }
62
63    #[test]
64    fn known_c04_value() {
65        let data = c04_data();
66        let entry = data.iter().find(|e| (e.mjd - 58849.0).abs() < 0.01);
67        let entry = entry.expect("MJD 58849 not found in C04");
68        assert!(
69            (entry.x_p - 0.076614).abs() < 0.001,
70            "xp={}, expected ~0.076614",
71            entry.x_p,
72        );
73    }
74
75    #[test]
76    fn timestamp_is_valid_iso8601() {
77        let ts = data_timestamp();
78        assert_eq!(ts.len(), 10, "timestamp '{}' wrong length", ts);
79        assert_eq!(&ts[4..5], "-");
80        assert_eq!(&ts[7..8], "-");
81        ts[0..4].parse::<u32>().expect("bad year");
82        ts[5..7].parse::<u32>().expect("bad month");
83        ts[8..10].parse::<u32>().expect("bad day");
84    }
85}