use a custom float parser

This commit is contained in:
yuankunzhang
2025-05-27 22:03:48 +08:00
parent 1552608bce
commit 60745300ad
3 changed files with 28 additions and 5 deletions
+19 -2
View File
@@ -145,9 +145,9 @@ where
/// following two forms:
///
/// - 0
/// - [+-][1-9][0-9]*
/// - [+-]?[1-9][0-9]*
///
/// Inputs like [+-]0[0-9]* (e.g., `+012`) are therefore rejected. We provide a
/// Inputs like [+-]?0[0-9]* (e.g., `+012`) are therefore rejected. We provide a
/// custom implementation to support such zero-prefixed integers.
fn dec_int<'a, E>(input: &mut &'a str) -> winnow::Result<i32, E>
where
@@ -175,6 +175,23 @@ where
.parse_next(input)
}
/// Parse a float number.
///
/// Rationale for not using `winnow::ascii::float`: the `float` parser provided
/// by winnow accepts E-notation numbers (e.g., `1.23e4`), whereas GNU date
/// rejects such numbers. To remain compatible with GNU date, we provide a
/// custom implementation that only accepts inputs like [+-]?[0-9]+(\.[0-9]+)?.
fn float<'a, E>(input: &mut &'a str) -> winnow::Result<f64, E>
where
E: ParserError<&'a str>,
{
(opt(one_of(['+', '-'])), digit1, opt(preceded('.', digit1)))
.void()
.take()
.verify_map(|s: &str| s.parse().ok())
.parse_next(input)
}
// Parse an item
pub fn parse_one(input: &mut &str) -> ModalResult<Item> {
trace(
+2 -2
View File
@@ -32,12 +32,12 @@
//! > this thursday.
use winnow::{
ascii::{alpha1, float},
ascii::alpha1,
combinator::{alt, opt},
ModalResult, Parser,
};
use super::{ordinal::ordinal, s};
use super::{float, ordinal::ordinal, s};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Relative {
+7 -1
View File
@@ -165,7 +165,13 @@ mod tests {
#[test]
fn invalid_formats() {
let invalid_dts = vec!["NotADate", "202104", "202104-12T22:37:47"];
let invalid_dts = vec![
"NotADate",
"202104",
"202104-12T22:37:47",
"a774e26sec", // 774e26 is not a valid seconds value (we don't accept E-notation)
"12.", // Invalid floating point number
];
for dt in invalid_dts {
assert_eq!(parse_datetime(dt), Err(ParseDateTimeError::InvalidInput));
}