Skip to content

Commit

Permalink
datetime_from_str is exact about whitespace
Browse files Browse the repository at this point in the history
`format/parse.rs:datetime_from_str` is exact about whitespace in
the passed data `s` and passed strftime format `fmt`

Issue #660
  • Loading branch information
jtmoon79 committed Aug 22, 2022
1 parent cd6d42b commit f9d90d1
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 13 deletions.
63 changes: 53 additions & 10 deletions src/datetime/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,19 +206,62 @@ fn test_datetime_from_str() {
}

#[test]
fn test_datetime_parse_from_str() {
let ymdhms = |y, m, d, h, n, s, off| FixedOffset::east(off).ymd(y, m, d).and_hms(h, n, s);
fn test_datetime_from_str_with_spaces() {
// should succeed
assert_eq!(
DateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
Ok(ymdhms(2014, 5, 7, 12, 34, 56, 570 * 60))
); // ignore offset
assert!(DateTime::parse_from_str("20140507000000", "%Y%m%d%H%M%S").is_err()); // no offset
assert!(DateTime::parse_from_str("Fri, 09 Aug 2013 23:54:35 GMT", "%a, %d %b %Y %H:%M:%S GMT")
.is_err());
Utc.datetime_from_str(" Aug 09 2013 23:54:35", " %b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str("Aug 09 2013 23:54:35 ", "%b %d %Y %H:%M:%S "),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str(" Aug 09 2013 23:54:35 ", " %b %d %Y %H:%M:%S "),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str(" Aug 09 2013 23:54:35", " %b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str(" Aug 09 2013 23:54:35", " %b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str("\tAug 09 2013 23:54:35", "\t%b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str("\tAug 09 2013 23:54:35\t", "\t%b %d %Y %H:%M:%S\t"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str("Aug 09 2013 23:54:35", "%b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
assert_eq!(
Utc.datetime_from_str("Aug 09 2013 23:54:35", "%b %d %Y %H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);

assert_eq!(
Utc.datetime_from_str("Aug 09 2013\t23:54:35", "%b %d %Y\t%H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);

assert_eq!(
Utc.datetime_from_str("Fri, 09 Aug 2013 23:54:35 GMT", "%a, %d %b %Y %H:%M:%S GMT"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35))
Utc.datetime_from_str("Aug 09 2013\t\t23:54:35", "%b %d %Y\t\t%H:%M:%S"),
Ok(Utc.ymd(2013, 8, 9).and_hms(23, 54, 35)),
);
// should fail
assert!(Utc.datetime_from_str(" Aug 09 2013 23:54:35", "%b %d %Y %H:%M:%S").is_err());
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35", " %b %d %Y %H:%M:%S").is_err());
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35\t", "%b %d %Y %H:%M:%S").is_err());
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35", "%b %d %Y %H:%M:%S\n").is_err());
assert!(Utc.datetime_from_str("\nAug 09 2013 23:54:35", "%b %d %Y %H:%M:%S\n").is_err());
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35 ", "%b %d %Y %H:%M:%S\n").is_err());
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35 ", "%b %d %Y\t%H:%M:%S").is_err());
}

#[test]
Expand Down
37 changes: 35 additions & 2 deletions src/format/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,41 @@ where
s = &s[prefix.len()..];
}

Item::Space(_) => {
s = s.trim_left();
Item::Space(space) => {
eprintln!("match Item::Space({:?})", space);
eprintln!(" s {:?}", s);
eprint!(" match s.chars().next() ");
match &s.chars().next() {
Some(c) => {
eprintln!("c {:?}", c);
if ! c.is_whitespace() {
// `s` whitespace must match each `item`
eprintln!("\n ~~Err(INVALID, {:?})", s);
return Err((s, INVALID));
}
// whitespace character must match
match &space.chars().next() {
Some(spacec) => {
if c != spacec {
eprintln!("\n ~~Err(INVALID, {:?})", s);
return Err((s, INVALID));
}
}
None => {
eprintln!("\n ~~Err(INVALID, {:?})", s);
return Err((s, INVALID));
}
}
s = &s[1..];
},
None => {
eprintln!("None");
// `s` whitespace must match each `items`
eprintln!("\n ~~Err(INVALID, {:?})", s);
return Err((s, INVALID));
}
}
eprintln!(" s {:?}", s);
}

#[cfg(any(feature = "alloc", feature = "std", test))]
Expand Down
9 changes: 8 additions & 1 deletion src/format/strftime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,21 @@ impl<'a> Iterator for StrftimeItems<'a> {

// the next item is space
Some(c) if c.is_whitespace() => {
eprintln!("match c.is_whitespace()");
// `%` is not a whitespace, so `c != '%'` is redundant
let nextspec = self
let mut nextspec = self
.remainder
.find(|c: char| !c.is_whitespace())
.unwrap_or(self.remainder.len());
if nextspec > 1 {
eprintln!(" nextspec {:?} set to 1", nextspec);
nextspec = 1;
}
assert!(nextspec > 0);
let item = sp!(&self.remainder[..nextspec]);
eprintln!(" remainder {:?}", self.remainder);
self.remainder = &self.remainder[nextspec..];
eprintln!(" remainder {:?}", self.remainder);
Some(item)
}

Expand Down

0 comments on commit f9d90d1

Please sign in to comment.