You've already forked parse_datetime
mirror of
https://github.com/uutils/parse_datetime.git
synced 2026-06-10 16:13:15 -07:00
Merge pull request #238 from stillbeingnick/bugfix/issue/coreutils-date-invalid
Changing ErrMode::Cut to ErrMode::Backtrack to allow alt parser flow (Fix for uutils/coreutils issue 8754)
This commit is contained in:
+14
-11
@@ -138,9 +138,10 @@ pub(super) fn iso1(input: &mut &str) -> ModalResult<Date> {
|
||||
let (year, _, month, _, day) =
|
||||
(year_str, s('-'), s(dec_uint), s('-'), s(dec_uint)).parse_next(input)?;
|
||||
|
||||
// Map err to Backtrack instead of Cut to avoid early termination of parsing
|
||||
(year, month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e)))
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
|
||||
}
|
||||
|
||||
/// Parse `[year][month][day]`
|
||||
@@ -156,7 +157,7 @@ pub(super) fn iso2(input: &mut &str) -> ModalResult<Date> {
|
||||
|
||||
(year, month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e)))
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
|
||||
}
|
||||
|
||||
/// Parse `[year]/[month]/[day]` or `[month]/[day]/[year]` or `[month]/[day]`.
|
||||
@@ -178,19 +179,21 @@ fn us(input: &mut &str) -> ModalResult<Date> {
|
||||
let day = day_from_str(s2)?;
|
||||
(s1, n, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e)))
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
|
||||
}
|
||||
Some(s2) => {
|
||||
// [month]/[day]/[year]
|
||||
let month = month_from_str(s1)?;
|
||||
(s2, month, n)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e)))
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
|
||||
}
|
||||
None => {
|
||||
// [month]/[day]
|
||||
let month = month_from_str(s1)?;
|
||||
(month, n).try_into().map_err(|e| ErrMode::Cut(ctx_err(e)))
|
||||
(month, n)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,10 +216,10 @@ fn literal1(input: &mut &str) -> ModalResult<Date> {
|
||||
match year {
|
||||
Some(year) => (year, month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e))),
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
|
||||
None => (month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e))),
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,10 +245,10 @@ fn literal2(input: &mut &str) -> ModalResult<Date> {
|
||||
match year {
|
||||
Some(year) => (year, month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e))),
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
|
||||
None => (month, day)
|
||||
.try_into()
|
||||
.map_err(|e| ErrMode::Cut(ctx_err(e))),
|
||||
.map_err(|e| ErrMode::Backtrack(ctx_err(e))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,12 +277,12 @@ fn literal_month(input: &mut &str) -> ModalResult<u8> {
|
||||
|
||||
fn month_from_str(s: &str) -> ModalResult<u8> {
|
||||
s.parse::<u8>()
|
||||
.map_err(|_| ErrMode::Cut(ctx_err("month must be a valid u8 number")))
|
||||
.map_err(|_| ErrMode::Backtrack(ctx_err("month must be a valid u8 number")))
|
||||
}
|
||||
|
||||
fn day_from_str(s: &str) -> ModalResult<u8> {
|
||||
s.parse::<u8>()
|
||||
.map_err(|_| ErrMode::Cut(ctx_err("day must be a valid u8 number")))
|
||||
.map_err(|_| ErrMode::Backtrack(ctx_err("day must be a valid u8 number")))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -128,3 +128,37 @@ fn test_time_invalid(#[case] input: &str) {
|
||||
"Input string '{input}' did not produce an error when parsing"
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::decimal_1_whole("1.123456789 seconds ago")]
|
||||
#[case::decimal_2_whole("12.123456789 seconds ago")]
|
||||
#[case::decimal_3_whole("123.123456789 seconds ago")]
|
||||
#[case::decimal_4_whole("1234.123456789 seconds ago")]
|
||||
#[case::decimal_5_whole("12345.123456789 seconds ago")]
|
||||
#[case::decimal_6_whole("123456.123456789 seconds ago")]
|
||||
#[case::decimal_7_whole("1234567.123456789 seconds ago")]
|
||||
#[case::decimal_8_whole("12345678.123456789 seconds ago")]
|
||||
#[case::decimal_9_whole("123456789.123456789 seconds ago")]
|
||||
#[case::decimal_10_whole("1234567891.123456789 seconds ago")]
|
||||
#[case::decimal_11_whole("12345678912.123456789 seconds ago")]
|
||||
#[case::decimal_12_whole("123456789123.123456789 seconds ago")]
|
||||
fn test_time_seconds_ago(#[case] input: &str) {
|
||||
let result = parse_datetime::parse_datetime(input);
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Input string '{input}', produced {result:?}, instead of Ok(Zoned)"
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::decimal_13_whole("1234567891234.123456789 seconds ago")]
|
||||
#[case::decimal_14_whole("12345678912345.123456789 seconds ago")]
|
||||
#[case::decimal_15_whole("123456789123456.123456789 seconds ago")]
|
||||
fn test_time_seconds_ago_invalid(#[case] input: &str) {
|
||||
let result = parse_datetime::parse_datetime(input);
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(parse_datetime::ParseDateTimeError::InvalidInput),
|
||||
"Input string '{input}' did not produce an error when parsing"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user