From d92249fce1a440eb012fd2d688775303c0c88115 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 23 Sep 2022 05:01:22 +0000 Subject: [PATCH] Support RFC3339 timestamps This extracts @lukesteensen's RFC 3339 timestamp parser from #377. This allows rust-tuf to interoperate better with other TUF implementations, which might include things like microseconds, or not be in the UTC timezone. --- tuf/src/interchange/cjson/shims.rs | 32 +++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tuf/src/interchange/cjson/shims.rs b/tuf/src/interchange/cjson/shims.rs index 9b125e9..13fb04f 100644 --- a/tuf/src/interchange/cjson/shims.rs +++ b/tuf/src/interchange/cjson/shims.rs @@ -11,7 +11,8 @@ use crate::Result; const SPEC_VERSION: &str = "1.0"; fn parse_datetime(ts: &str) -> Result> { - Utc.datetime_from_str(ts, "%FT%TZ") + DateTime::parse_from_rfc3339(ts) + .map(|ts| ts.with_timezone(&Utc)) .map_err(|e| Error::Encoding(format!("Can't parse DateTime: {:?}", e))) } @@ -570,3 +571,32 @@ mod deserialize_reject_duplicates { }) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn datetime_formats() { + // The TUF spec says datetimes should be in ISO8601 format, specifically + // "YYYY-MM-DDTHH:MM:SSZ". Since not all TUF clients adhere strictly to that, we choose to + // be more lenient here. The following represent the intersection of valid ISO8601 and + // RFC3339 datetime formats (source: https://ijmacd.github.io/rfc3339-iso8601/). + let valid_formats = [ + "2022-08-30T19:53:55Z", + "2022-08-30T19:53:55.7Z", + "2022-08-30T19:53:55.77Z", + "2022-08-30T19:53:55.775Z", + "2022-08-30T19:53:55+00:00", + "2022-08-30T19:53:55.7+00:00", + "2022-08-30T14:53:55-05:00", + "2022-08-30T14:53:55.7-05:00", + "2022-08-30T14:53:55.77-05:00", + "2022-08-30T14:53:55.775-05:00", + ]; + + for format in valid_formats { + assert!(parse_datetime(format).is_ok(), "should parse {:?}", format); + } + } +}