Skip to content

Commit d6574bd

Browse files
fix: Elements::from_line rounding error when parsing epoch
Fix a bug where some (valid) epochs would result in `Elements::from_lines` failing. Simple change that checks for nanosecond overflow and corrects it before `chrono::NaiveTime::from_num_seconds_from_midnight_opt` gets called.
1 parent db7b712 commit d6574bd

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

src/tle.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,12 @@ impl Elements {
704704
end: 32,
705705
})?;
706706
let seconds = day.fract() * (24.0 * 60.0 * 60.0);
707+
let mut nsecs = (seconds.fract() * 1e9).round() as u32;
708+
let mut seconds = seconds as u32;
709+
if nsecs >= 1_000_000_000 {
710+
nsecs -= 1_000_000_000;
711+
seconds += 1;
712+
}
707713
chrono::NaiveDate::from_yo_opt(
708714
match line1[18..20].parse::<u8>().map_err(|_| Error {
709715
what: ErrorWhat::ExpectedFloat,
@@ -723,16 +729,14 @@ impl Elements {
723729
end: 20,
724730
})?
725731
.and_time(
726-
chrono::NaiveTime::from_num_seconds_from_midnight_opt(
727-
seconds as u32,
728-
(seconds.fract() * 1e9).round() as u32,
729-
)
730-
.ok_or(Error {
731-
what: ErrorWhat::FromNumSecondsFromMidnightFailed,
732-
line: ErrorLine::Line1,
733-
start: 20,
734-
end: 32,
735-
})?,
732+
chrono::NaiveTime::from_num_seconds_from_midnight_opt(seconds, nsecs).ok_or(
733+
Error {
734+
what: ErrorWhat::FromNumSecondsFromMidnightFailed,
735+
line: ErrorLine::Line1,
736+
start: 20,
737+
end: 32,
738+
},
739+
)?,
736740
)
737741
},
738742
mean_motion_dot: line1[33..43]
@@ -1266,6 +1270,24 @@ mod tests {
12661270
assert_eq_f64(elements.mean_anomaly, 10.4117);
12671271
assert_eq_f64(elements.mean_motion, 2.28537848);
12681272
assert_eq!(elements.revolution_number, 1);
1273+
1274+
Ok(())
1275+
}
1276+
1277+
#[test]
1278+
fn from_tle_rounding_error_prone_epoch() -> core::result::Result<(), Error> {
1279+
let elements = Elements::from_tle(
1280+
Some("ISS (ZARYA)".to_string()),
1281+
"1 25544U 98067A 23001.00031250 .00023190 00000-0 40700-3 0 9996".as_bytes(),
1282+
"2 25544 51.6422 151.7482 0002260 30.8955 315.0781 15.50422841429866".as_bytes(),
1283+
)?;
1284+
assert_eq!(
1285+
elements.datetime,
1286+
chrono::NaiveDate::from_ymd_opt(2023, 1, 1)
1287+
.and_then(|date| date.and_hms_opt(0, 0, 27))
1288+
.unwrap()
1289+
);
1290+
12691291
Ok(())
12701292
}
12711293

0 commit comments

Comments
 (0)