1
0
mirror of https://github.com/bspeice/dtparse synced 2024-11-14 09:58:09 -05:00

fix: invalid timezone should return err not panic

1. Enhanced time zone check

2. modify default NaiveDate value set 1970-01-01 not today
This commit is contained in:
taichong 2024-08-19 09:12:53 +08:00
parent 081cd7bea0
commit 7867769ecd
2 changed files with 102 additions and 9 deletions

View File

@ -713,9 +713,12 @@ impl Parser {
ignoretz: bool,
tzinfos: &HashMap<String, i32>,
) -> ParseResult<(NaiveDateTime, Option<FixedOffset>, Option<Vec<String>>)> {
let default_date = default.unwrap_or(&Local::now().naive_local()).date();
let default_ts = NaiveDateTime::new(default_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap());
// If default is none, 1970-01-01 00:00:00 as default value is better.
let default_date = default
.unwrap_or(&NaiveDate::default().and_hms_opt(0, 0, 0).unwrap())
.date();
let default_ts =
NaiveDateTime::new(default_date, NaiveTime::from_hms_opt(0, 0, 0).unwrap());
let (res, tokens) =
self.parse_with_tokens(timestr, dayfirst, yearfirst, fuzzy, fuzzy_with_tokens)?;
@ -840,28 +843,54 @@ impl Parser {
}
} else if res.hour.is_some() && (l[i] == "+" || l[i] == "-") {
let signal = if l[i] == "+" { 1 } else { -1 };
let len_li = l[i].len();
// check next index's length
let timezone_len = l[i + 1].len();
let mut hour_offset: Option<i32> = None;
let mut min_offset: Option<i32> = None;
// TODO: check that l[i + 1] is integer?
if len_li == 4 {
if timezone_len == 4 {
// -0300
hour_offset = Some(l[i + 1][..2].parse::<i32>()?);
min_offset = Some(l[i + 1][2..4].parse::<i32>()?);
} else if i + 2 < len_l && l[i + 2] == ":" {
// -03:00
hour_offset = Some(l[i + 1].parse::<i32>()?);
min_offset = Some(l[i + 3].parse::<i32>()?);
let hour_offset_len = l[i + 1].len();
// -003:00 need err
if hour_offset_len <= 2 {
let range_len = min(hour_offset_len, 2);
hour_offset = Some(l[i + 1][..range_len].parse::<i32>()?);
} else {
return Err(ParseError::TimezoneUnsupported);
}
// if timezone is wrong format like "-03:" just return a Err, should not panic.
if i + 3 > l.len() - 1 {
return Err(ParseError::TimezoneUnsupported);
}
let min_offset_len = l[i + 3].len();
// -09:003 need err
if min_offset_len <= 2 {
let range_len = min(min_offset_len, 2);
min_offset = Some(l[i + 3][..range_len].parse::<i32>()?);
} else {
return Err(ParseError::TimezoneUnsupported);
}
i += 2;
} else if len_li <= 2 {
} else if timezone_len <= 2 {
// -[0]3
let range_len = min(l[i + 1].len(), 2);
hour_offset = Some(l[i + 1][..range_len].parse::<i32>()?);
min_offset = Some(0);
}
// like +09123
if hour_offset.is_none() && min_offset.is_none() {
return Err(ParseError::TimezoneUnsupported);
}
res.tzoffset =
Some(signal * (hour_offset.unwrap() * 3600 + min_offset.unwrap() * 60));

View File

@ -103,4 +103,68 @@ fn github_45() {
assert!(parse("/2018-fifa-").is_err());
assert!(parse("/2009/07/").is_err());
assert!(parse("2021-09-").is_err());
}
}
#[test]
fn github_46() {
assert_eq!(
parse("2000-01-01 12:00:00+00:"),
Err(ParseError::TimezoneUnsupported)
);
assert_eq!(
parse("2000-01-01 12:00:00+09123"),
Err(ParseError::TimezoneUnsupported)
);
assert_eq!(
parse("2000-01-01 13:00:00+00:003"),
Err(ParseError::TimezoneUnsupported)
);
assert_eq!(
parse("2000-01-01 13:00:00+009:03"),
Err(ParseError::TimezoneUnsupported)
);
assert_eq!(
parse("2000-01-01 13:00:00+xx:03"),
Err(ParseError::InvalidNumeric(
"invalid digit found in string".to_owned()
))
);
assert_eq!(
parse("2000-01-01 13:00:00+00:yz"),
Err(ParseError::InvalidNumeric(
"invalid digit found in string".to_owned()
))
);
let mut parse_result = parse("2000-01-01 13:00:00+00:03");
match parse_result {
Ok((dt, offset)) => {
assert_eq!(format!("{:?}", dt), "2000-01-01T13:00:00".to_string());
assert_eq!(format!("{:?}", offset), "Some(+00:03)".to_string());
}
Err(_) => {
panic!();
}
};
parse_result = parse("2000-01-01 12:00:00+0811");
match parse_result {
Ok((dt, offset)) => {
assert_eq!(format!("{:?}", dt), "2000-01-01T12:00:00".to_string());
assert_eq!(format!("{:?}", offset), "Some(+08:11)".to_string());
}
Err(_) => {
panic!();
}
}
parse_result = parse("2000");
match parse_result {
Ok((dt, offset)) => {
assert_eq!(format!("{:?}", dt), "2000-01-01T00:00:00".to_string());
assert!(offset.is_none());
}
Err(_) => {
panic!();
}
}
}