mirror of
https://github.com/bspeice/dtparse
synced 2025-07-06 16:24:57 -04:00
#40: Nanosecond precision
This commit is contained in:
24
src/lib.rs
24
src/lib.rs
@ -617,7 +617,7 @@ struct ParsingResult {
|
||||
hour: Option<i32>,
|
||||
minute: Option<i32>,
|
||||
second: Option<i32>,
|
||||
microsecond: Option<i32>,
|
||||
nanosecond: Option<i64>,
|
||||
tzname: Option<String>,
|
||||
tzoffset: Option<i32>,
|
||||
ampm: Option<bool>,
|
||||
@ -644,7 +644,7 @@ impl ParsingResult {
|
||||
+ option_len!(self.hour)
|
||||
+ option_len!(self.minute)
|
||||
+ option_len!(self.second)
|
||||
+ option_len!(self.microsecond)
|
||||
+ option_len!(self.nanosecond)
|
||||
+ option_len!(self.tzname)
|
||||
+ option_len!(self.ampm)
|
||||
}
|
||||
@ -976,18 +976,18 @@ impl Parser {
|
||||
let hour = res.hour.unwrap_or(default.hour() as i32) as u32;
|
||||
let minute = res.minute.unwrap_or(default.minute() as i32) as u32;
|
||||
let second = res.second.unwrap_or(default.second() as i32) as u32;
|
||||
let microsecond = res
|
||||
.microsecond
|
||||
.unwrap_or(default.timestamp_subsec_micros() as i32) as u32;
|
||||
let nanosecond = res
|
||||
.nanosecond
|
||||
.unwrap_or(default.timestamp_subsec_nanos() as i64) as u32;
|
||||
let t =
|
||||
NaiveTime::from_hms_micro_opt(hour, minute, second, microsecond).ok_or_else(|| {
|
||||
NaiveTime::from_hms_nano_opt(hour, minute, second, nanosecond).ok_or_else(|| {
|
||||
if hour >= 24 {
|
||||
ParseError::ImpossibleTimestamp("Invalid hour")
|
||||
} else if minute >= 60 {
|
||||
ParseError::ImpossibleTimestamp("Invalid minute")
|
||||
} else if second >= 60 {
|
||||
ParseError::ImpossibleTimestamp("Invalid second")
|
||||
} else if microsecond >= 2_000_000 {
|
||||
} else if nanosecond >= 2_000_000_000 {
|
||||
ParseError::ImpossibleTimestamp("Invalid microsecond")
|
||||
} else {
|
||||
unreachable!();
|
||||
@ -1071,7 +1071,7 @@ impl Parser {
|
||||
|
||||
let t = self.parsems(&s[4..])?;
|
||||
res.second = Some(t.0);
|
||||
res.microsecond = Some(t.1);
|
||||
res.nanosecond = Some(t.1);
|
||||
}
|
||||
} else if vec![8, 12, 14].contains(&len_li) {
|
||||
// YYMMDD
|
||||
@ -1109,7 +1109,7 @@ impl Parser {
|
||||
// TODO: (x, y) = (a, b) syntax?
|
||||
let ms = self.parsems(&tokens[idx + 4]).unwrap();
|
||||
res.second = Some(ms.0);
|
||||
res.microsecond = Some(ms.1);
|
||||
res.nanosecond = Some(ms.1);
|
||||
|
||||
idx += 2;
|
||||
}
|
||||
@ -1183,13 +1183,13 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn parsems(&self, seconds_str: &str) -> ParseResult<(i32, i32)> {
|
||||
fn parsems(&self, seconds_str: &str) -> ParseResult<(i32, i64)> {
|
||||
if seconds_str.contains('.') {
|
||||
let split: Vec<&str> = seconds_str.split('.').collect();
|
||||
let (i, f): (&str, &str) = (split[0], split[1]);
|
||||
|
||||
let i_parse = i.parse::<i32>()?;
|
||||
let f_parse = ljust(f, 6, '0').parse::<i32>()?;
|
||||
let f_parse = ljust(f, 9, '0').parse::<i64>()?;
|
||||
Ok((i_parse, f_parse))
|
||||
} else {
|
||||
Ok((seconds_str.parse::<i32>()?, 0))
|
||||
@ -1281,7 +1281,7 @@ impl Parser {
|
||||
} else if hms == 2 {
|
||||
let (sec, micro) = self.parsems(value_repr).unwrap();
|
||||
res.second = Some(sec);
|
||||
res.microsecond = Some(micro);
|
||||
res.nanosecond = Some(micro);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1,3 +1,14 @@
|
||||
mod fuzzing;
|
||||
mod pycompat_parser;
|
||||
mod pycompat_tokenizer;
|
||||
|
||||
use chrono::NaiveDate;
|
||||
use crate::parse;
|
||||
|
||||
#[test]
|
||||
fn nanosecond_precision() {
|
||||
assert_eq!(
|
||||
parse("2008.12.29T08:09:10.123456789").unwrap(),
|
||||
(NaiveDate::from_ymd_opt(2008, 12, 29).unwrap().and_hms_nano_opt(8, 9, 10, 123_456_789).unwrap(), None)
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user