diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 04913da2e6..ec6ed4fe0e 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -16,10 +16,12 @@ use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(feature = "unstable-locales")] use crate::format::Locale; -use crate::format::{parse, parse_and_remainder, ParseError, ParseResult, Parsed, StrftimeItems}; +use crate::format::{ + parse, parse_and_remainder, parse_rfc3339, Fixed, Item, ParseError, ParseResult, Parsed, + StrftimeItems, TOO_LONG, +}; #[cfg(any(feature = "alloc", feature = "std"))] use crate::format::{write_rfc3339, DelayedFormat}; -use crate::format::{Fixed, Item}; use crate::naive::{Days, IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] use crate::offset::Local; @@ -699,9 +701,11 @@ impl DateTime { /// also simultaneously valid RFC 3339 values, but not all RFC 3339 values are valid ISO 8601 /// values (or the other way around). pub fn parse_from_rfc3339(s: &str) -> ParseResult> { - const ITEMS: &[Item<'static>] = &[Item::Fixed(Fixed::RFC3339)]; let mut parsed = Parsed::new(); - parse(&mut parsed, s, ITEMS.iter())?; + let (s, _) = parse_rfc3339(&mut parsed, s)?; + if !s.is_empty() { + return Err(TOO_LONG); + } parsed.to_datetime() } diff --git a/src/format/mod.rs b/src/format/mod.rs index 6932a66f5b..976eef1ac0 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -69,6 +69,7 @@ pub use formatting::{format_item_localized, format_localized}; pub use locales::Locale; #[cfg(all(not(feature = "unstable-locales"), any(feature = "alloc", feature = "std")))] pub(crate) use locales::Locale; +pub(crate) use parse::parse_rfc3339; pub use parse::{parse, parse_and_remainder}; pub use parsed::Parsed; pub use strftime::StrftimeItems; @@ -450,7 +451,7 @@ const IMPOSSIBLE: ParseError = ParseError(ParseErrorKind::Impossible); const NOT_ENOUGH: ParseError = ParseError(ParseErrorKind::NotEnough); const INVALID: ParseError = ParseError(ParseErrorKind::Invalid); const TOO_SHORT: ParseError = ParseError(ParseErrorKind::TooShort); -const TOO_LONG: ParseError = ParseError(ParseErrorKind::TooLong); +pub(crate) const TOO_LONG: ParseError = ParseError(ParseErrorKind::TooLong); const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat); // this implementation is here only because we need some private code from `scan` diff --git a/src/format/parse.rs b/src/format/parse.rs index b3099672aa..d288895084 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -155,7 +155,7 @@ fn parse_rfc2822<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a st Ok((s, ())) } -fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> { +pub(crate) fn parse_rfc3339<'a>(parsed: &mut Parsed, mut s: &'a str) -> ParseResult<(&'a str, ())> { macro_rules! try_consume { ($e:expr) => {{ let (s_, v) = $e?; @@ -1817,15 +1817,9 @@ mod tests { ("2015-01-20T00:00:1-08:00", Err(INVALID)), // missing complete S ]; - fn rfc3339_to_datetime(date: &str) -> ParseResult> { - let mut parsed = Parsed::new(); - parse(&mut parsed, date, [Item::Fixed(Fixed::RFC3339)].iter())?; - parsed.to_datetime() - } - // Test against test data above for &(date, checkdate) in testdates.iter() { - let dt = rfc3339_to_datetime(date); // parse a date + let dt = DateTime::::parse_from_rfc3339(date); if dt != checkdate { // check for expected result panic!(