Skip to content

Commit

Permalink
Add support for ddd KVN dates
Browse files Browse the repository at this point in the history
  • Loading branch information
matzipan committed Feb 12, 2025
1 parent 2d1e3f2 commit 8a41507
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 29 deletions.
3 changes: 1 addition & 2 deletions crates/lox-io/src/ndm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
//! covariance matrix section. But this will cause the comments for the
//! following section, the maneuver parameters list, to be discarded.
//!
//! The KVN parsing currently does not support user-defined fields and ddd date
//! format types.
//! The KVN parsing currently does not support user-defined fields.
//!
//! Check the respective submodules for more information.
Expand Down
90 changes: 63 additions & 27 deletions crates/lox-io/src/ndm/kvn/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,23 @@ pub struct KvnValue<V, U> {
pub unit: Option<U>,
}

#[derive(PartialEq, Debug)]
pub enum DateOfYear {
DayOfMonth { month: u8, day: u8 },
DayOfYear { day: u16 },
}

impl Default for DateOfYear {
fn default() -> Self {
DateOfYear::DayOfMonth { month: 0, day: 0 }
}
}

#[derive(PartialEq, Debug, Default)]
pub struct KvnDateTimeValue {
pub year: u16,
pub month: u8,
pub day: u8,
pub date_in_year: DateOfYear,

pub hour: u8,
pub minute: u8,
pub second: u8,
Expand Down Expand Up @@ -580,13 +592,21 @@ pub fn handle_datetime_capture(captures: &regex::Captures) -> KvnDateTimeValue {
// We don't do full validation of the date values. We only care if they
// have the expected number of digits

// mo is a mandatory decimal in the regex so we expect the capture to be
// always there and unwrap is fine
let month = captures.name("mo").unwrap().as_str().parse::<u8>().unwrap();
let date_in_year = if let Some(day) = captures.name("ddd") {
let day = day.as_str().parse::<u8>().unwrap();

// day is a mandatory decimal in the regex so we expect the capture to be
// always there and unwrap is fine
let day = captures.name("dy").unwrap().as_str().parse::<u8>().unwrap();
DateOfYear::DayOfYear { day }
} else {
// mo is a mandatory decimal in the regex so we expect the capture to be
// always there and unwrap is fine
let month = captures.name("mo").unwrap().as_str().parse::<u8>().unwrap();

// day is a mandatory decimal in the regex so we expect the capture to be
// always there and unwrap is fine
let day = captures.name("dy").unwrap().as_str().parse::<u8>().unwrap();

DateOfYear::DayOfMonth { month, day }
};

// hr is a mandatory decimal in the regex so we expect the capture to be
// always there and unwrap is fine
Expand Down Expand Up @@ -617,8 +637,7 @@ pub fn handle_datetime_capture(captures: &regex::Captures) -> KvnDateTimeValue {

KvnDateTimeValue {
year,
month,
day,
date_in_year,
hour,
minute,
second,
Expand All @@ -634,8 +653,8 @@ pub fn parse_kvn_datetime_line(
Err(KvnDateTimeParserErr::EmptyValue { input })?
};

// Modified from Figure F-5: CCSDS 502.0-B-3
let re = Regex::new(r"^(?:\s*)?(?<keyword>[0-9A-Z_]*)(?:\s*)?=(?:\s*)?(?<full_date_value>(?<yr>(?:\d{4}))-(?<mo>(?:\d{1,2}))-(?<dy>(?:\d{1,2}))T(?<hr>(?:\d{1,2})):(?<mn>(?:\d{1,2})):(?<sc>(?:\d{0,2}(?:\.\d*)?)))(?:\s*)?$").unwrap();
// Modified from Figure F-5: CCSDS 502.0-B-3 with extension for ddd
let re = Regex::new(r"^(?:\s*)?(?<keyword>[0-9A-Z_]*)(?:\s*)?=(?:\s*)?(?<full_date_value>(?<yr>(?:\d{4}))-((?<mo>(?:\d{1,2}))-(?<dy>(?:\d{1,2})))?(?<ddd>(?:\d{3}))?T(?<hr>(?:\d{1,2})):(?<mn>(?:\d{1,2})):(?<sc>(?:\d{0,2}(?:\.\d*)?)))(?:\s*)?$").unwrap();

let captures = re
.captures(input)
Expand Down Expand Up @@ -974,8 +993,7 @@ mod test {
parse_kvn_datetime_line("CREATION_DATE = 2021-06-03T05:33:00.123"),
Ok(KvnDateTimeValue {
year: 2021,
month: 6,
day: 3,
date_in_year: DateOfYear::DayOfMonth { month: 6, day: 3 },
hour: 5,
minute: 33,
second: 0,
Expand All @@ -988,8 +1006,7 @@ mod test {
parse_kvn_datetime_line("CREATION_DATE = 2021-06-03T05:33:01"),
Ok(KvnDateTimeValue {
year: 2021,
month: 6,
day: 3,
date_in_year: DateOfYear::DayOfMonth { month: 6, day: 3 },
hour: 5,
minute: 33,
second: 1,
Expand All @@ -1004,8 +1021,7 @@ mod test {
parse_kvn_datetime_line("CREATION_DATE = 2021-06-03T05:33:01 "),
Ok(KvnDateTimeValue {
year: 2021,
month: 6,
day: 3,
date_in_year: DateOfYear::DayOfMonth { month: 6, day: 3 },
hour: 5,
minute: 33,
second: 1,
Expand All @@ -1020,8 +1036,7 @@ mod test {
parse_kvn_datetime_line(" CREATION_DATE = 2021-06-03T05:33:01"),
Ok(KvnDateTimeValue {
year: 2021,
month: 6,
day: 3,
date_in_year: DateOfYear::DayOfMonth { month: 6, day: 3 },
hour: 5,
minute: 33,
second: 1,
Expand All @@ -1030,7 +1045,31 @@ mod test {
})
);

// @TODO add support for ddd format
assert_eq!(
parse_kvn_datetime_line("CREATION_DATE = 2021-090T05:33:01"),
Ok(KvnDateTimeValue {
year: 2021,
date_in_year: DateOfYear::DayOfYear { day: 90 },
hour: 5,
minute: 33,
second: 1,
fractional_second: 0.0,
full_value: "2021-090T05:33:01".to_string(),
})
);

assert_eq!(
parse_kvn_datetime_line("CREATION_DATE = 2021-366T05:33:01"),
Ok(KvnDateTimeValue {
year: 2021,
date_in_year: DateOfYear::DayOfYear { day: 366 },
hour: 5,
minute: 33,
second: 1,
fractional_second: 0.0,
full_value: "2021-090T05:33:01".to_string(),
})
);

assert_eq!(
parse_kvn_datetime_line("CREATION_DATE = 2021,06,03Q05!33!00-123"),
Expand Down Expand Up @@ -1130,8 +1169,7 @@ mod test {
Ok(KvnStateVectorValue {
epoch: KvnDateTimeValue {
year: 1996,
month: 12,
day: 28,
date_in_year: DateOfYear::DayOfMonth { month: 12, day: 28 },
hour: 21,
minute: 29,
second: 7,
Expand Down Expand Up @@ -1160,8 +1198,7 @@ mod test {
Ok(KvnStateVectorValue {
epoch: KvnDateTimeValue {
year: 1996,
month: 12,
day: 28,
date_in_year: DateOfYear::DayOfMonth { month: 12, day: 28 },
hour: 21,
minute: 29,
second: 7,
Expand Down Expand Up @@ -1190,8 +1227,7 @@ mod test {
Ok(KvnStateVectorValue {
epoch: KvnDateTimeValue {
year: 1996,
month: 12,
day: 28,
date_in_year: DateOfYear::DayOfMonth { month: 12, day: 28 },
hour: 21,
minute: 29,
second: 7,
Expand Down

0 comments on commit 8a41507

Please sign in to comment.