Parse deltas
This commit is contained in:
parent
107966389c
commit
a8ddaefa78
2 changed files with 48 additions and 2 deletions
|
|
@ -1,5 +1,15 @@
|
||||||
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
|
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Delta {
|
||||||
|
pub years: i32,
|
||||||
|
pub months: i32,
|
||||||
|
pub weeks: i32,
|
||||||
|
pub days: i32,
|
||||||
|
pub hours: i32,
|
||||||
|
pub minutes: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DateDelta {
|
struct DateDelta {
|
||||||
years: i32,
|
years: i32,
|
||||||
|
|
|
||||||
40
src/parse.rs
40
src/parse.rs
|
|
@ -1,13 +1,15 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use chrono::{NaiveDate, NaiveTime};
|
use chrono::{Duration, NaiveDate, NaiveTime};
|
||||||
use nom::branch::Alt;
|
use nom::branch::Alt;
|
||||||
use nom::bytes::complete::{take_while1, take_while_m_n};
|
use nom::bytes::complete::{take_while1, take_while_m_n};
|
||||||
use nom::character::complete::{char, digit1, newline};
|
use nom::character::complete::{char, digit1, newline};
|
||||||
use nom::combinator::{eof, fail, map_opt, map_res};
|
use nom::combinator::{eof, fail, map_opt, map_res, opt, value};
|
||||||
use nom::sequence::terminated;
|
use nom::sequence::terminated;
|
||||||
use nom::{IResult, Parser};
|
use nom::{IResult, Parser};
|
||||||
|
|
||||||
|
use crate::commands::Delta;
|
||||||
|
|
||||||
fn line_ending(i: &str) -> IResult<&str, ()> {
|
fn line_ending(i: &str) -> IResult<&str, ()> {
|
||||||
(newline.map(|_| ()), eof.map(|_| ())).choice(i)
|
(newline.map(|_| ()), eof.map(|_| ())).choice(i)
|
||||||
}
|
}
|
||||||
|
|
@ -50,6 +52,40 @@ fn time(i: &str) -> IResult<&str, NaiveTime> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn single_delta<const C: char>(i: &str) -> IResult<&str, i32> {
|
||||||
|
let (i, sign) = (value(1, char('+')), value(-1, char('-'))).choice(i)?;
|
||||||
|
let (i, amount) = opt(number::<i32>)(i)?;
|
||||||
|
let amount = amount.unwrap_or(1);
|
||||||
|
Ok((i, sign * amount))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opt_single_delta<const C: char>(i: &str) -> IResult<&str, i32> {
|
||||||
|
let (i, delta) = opt(single_delta::<C>)(i)?;
|
||||||
|
let delta = delta.unwrap_or(0);
|
||||||
|
Ok((i, delta))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delta(i: &str) -> IResult<&str, Delta> {
|
||||||
|
// TODO Require at least one field?
|
||||||
|
let (i, years) = opt_single_delta::<'y'>(i)?;
|
||||||
|
let (i, months) = opt_single_delta::<'m'>(i)?;
|
||||||
|
let (i, weeks) = opt_single_delta::<'w'>(i)?;
|
||||||
|
let (i, days) = opt_single_delta::<'d'>(i)?;
|
||||||
|
let (i, hours) = opt_single_delta::<'h'>(i)?;
|
||||||
|
let (i, minutes) = opt_single_delta::<'m'>(i)?;
|
||||||
|
Ok((
|
||||||
|
i,
|
||||||
|
Delta {
|
||||||
|
years,
|
||||||
|
months,
|
||||||
|
weeks,
|
||||||
|
days,
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue