Only parse up to max number of digits for nanoseconds w/o dots

This commit is contained in:
Evan Schwartz 2018-06-08 18:47:38 -04:00
parent 074e92fc63
commit 8a2b09962a
2 changed files with 49 additions and 16 deletions

View File

@ -5,6 +5,7 @@
//! Date and time parsing routines.
use std::usize;
use std::cmp;
use Weekday;
@ -315,9 +316,26 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<(
}
}
Nanosecond3NoDot | Nanosecond6NoDot | Nanosecond9NoDot => {
Nanosecond3NoDot => {
if !s.is_empty() {
let nano = try_consume!(scan::nanosecond(&s[..]));
let max_index = cmp::min(s.len() as u64, 3) as usize;
let nano = try_consume!(scan::nanosecond(&s[..max_index]));
try!(parsed.set_nanosecond(nano));
}
}
Nanosecond6NoDot => {
if !s.is_empty() {
let max_index = cmp::min(s.len() as u64, 6) as usize;
let nano = try_consume!(scan::nanosecond(&s[..max_index]));
try!(parsed.set_nanosecond(nano));
}
}
Nanosecond9NoDot => {
if !s.is_empty() {
let max_index = cmp::min(s.len() as u64, 9) as usize;
let nano = try_consume!(scan::nanosecond(&s[..max_index]));
try!(parsed.set_nanosecond(nano));
}
}
@ -547,15 +565,40 @@ fn test_parse() {
check!("4", [fix!(Nanosecond3NoDot)]; nanosecond: 400_000_000);
check!("42", [fix!(Nanosecond3NoDot)]; nanosecond: 420_000_000);
check!("421", [fix!(Nanosecond3NoDot)]; nanosecond: 421_000_000);
check!("42195", [fix!(Nanosecond3NoDot)]; nanosecond: 421_950_000);
check!("421950803", [fix!(Nanosecond3NoDot)]; nanosecond: 421_950_803);
check!("421950803547", [fix!(Nanosecond3NoDot)]; nanosecond: 421_950_803);
check!("000000003547", [fix!(Nanosecond3NoDot)]; nanosecond: 3);
check!("42195", [fix!(Nanosecond3NoDot)]; nanosecond: 421_000_000); // ignores everything after 3 digits
check!("000000000547", [fix!(Nanosecond3NoDot)]; nanosecond: 0);
check!("4x", [fix!(Nanosecond3NoDot)]; TOO_LONG);
check!(" 4", [fix!(Nanosecond3NoDot)]; INVALID);
check!(".421", [fix!(Nanosecond3NoDot)]; INVALID);
check!("", [fix!(Nanosecond6NoDot)]; ); // no field set, but not an error
check!("0", [fix!(Nanosecond6NoDot)]; nanosecond: 0);
check!("4", [fix!(Nanosecond6NoDot)]; nanosecond: 400_000_000);
check!("42", [fix!(Nanosecond6NoDot)]; nanosecond: 420_000_000);
check!("421", [fix!(Nanosecond6NoDot)]; nanosecond: 421_000_000);
check!("42195", [fix!(Nanosecond6NoDot)]; nanosecond: 421_950_000);
check!("421950803", [fix!(Nanosecond6NoDot)]; nanosecond: 421_950_000); // ignores everything after 6 digits
check!("000003547", [fix!(Nanosecond6NoDot)]; nanosecond: 3000);
check!("000000547", [fix!(Nanosecond6NoDot)]; nanosecond: 0);
check!("4x", [fix!(Nanosecond6NoDot)]; TOO_LONG);
check!(" 4", [fix!(Nanosecond6NoDot)]; INVALID);
check!(".421", [fix!(Nanosecond6NoDot)]; INVALID);
check!("", [fix!(Nanosecond9NoDot)]; ); // no field set, but not an error
check!("0", [fix!(Nanosecond9NoDot)]; nanosecond: 0);
check!("4", [fix!(Nanosecond9NoDot)]; nanosecond: 400_000_000);
check!("42", [fix!(Nanosecond9NoDot)]; nanosecond: 420_000_000);
check!("421", [fix!(Nanosecond9NoDot)]; nanosecond: 421_000_000);
check!("42195", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_000);
check!("421950803", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_803);
check!("421950803547", [fix!(Nanosecond9NoDot)]; nanosecond: 421_950_803);
// check!("421950803547", [fix!(Nanosecond9NoDot), num!(Second)]; nanosecond: 421_950_803, second: 54); // don't skip digits that come after the 9
check!("000000003547", [fix!(Nanosecond9NoDot)]; nanosecond: 3);
check!("000000000547", [fix!(Nanosecond9NoDot)]; nanosecond: 0);
check!("4x", [fix!(Nanosecond9NoDot)]; TOO_LONG);
check!(" 4", [fix!(Nanosecond9NoDot)]; INVALID);
check!(".421", [fix!(Nanosecond9NoDot)]; INVALID);
// fixed: timezone offsets
check!("+00:00", [fix!(TimezoneOffset)]; offset: 0);
check!("-00:00", [fix!(TimezoneOffset)]; offset: 0);

View File

@ -246,16 +246,6 @@ impl Parsed {
set_if_consistent(&mut self.nanosecond, try!(value.to_u32().ok_or(OUT_OF_RANGE)))
}
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
pub fn set_millisecond(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.nanosecond, try!(value.to_u32().ok_or(OUT_OF_RANGE)) * 1_000_000)
}
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
pub fn set_microsecond(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.nanosecond, try!(value.to_u32().ok_or(OUT_OF_RANGE)) * 1_000)
}
/// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
pub fn set_timestamp(&mut self, value: i64) -> ParseResult<()> {
set_if_consistent(&mut self.timestamp, value)