Add date parsing
This commit is contained in:
parent
d29928aa3c
commit
33d0897096
|
@ -107,6 +107,7 @@ pub fn parse_date_field(s: &str) -> Result<Vec<Date>, Error> {
|
||||||
Ok(dates)
|
Ok(dates)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -158,3 +159,4 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{Color, Date, Error, GameResult};
|
use crate::{Color, Date, Error, GameResult};
|
||||||
|
use chrono::{Datelike, NaiveDate};
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{escaped_transform, tag, take_until1},
|
bytes::complete::{escaped_transform, tag, take_until1},
|
||||||
|
@ -815,6 +816,81 @@ fn parse_text<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, String, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DateSegment {
|
||||||
|
One(i32),
|
||||||
|
Two(i32, i32),
|
||||||
|
Three(i32, i32, i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_date_field<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, Vec<Date>, E> {
|
||||||
|
|input| {
|
||||||
|
let (input, first_date) = parse_date().parse(input)?;
|
||||||
|
let (input, mut more_dates) = many0(parse_date_segment())(input)?;
|
||||||
|
|
||||||
|
let mut date_segments = vec![first_date];
|
||||||
|
date_segments.append(&mut more_dates);
|
||||||
|
|
||||||
|
let mut dates = vec![];
|
||||||
|
let mut most_recent = None;
|
||||||
|
|
||||||
|
for date_segment in date_segments {
|
||||||
|
let new_date = match date_segment {
|
||||||
|
DateSegment::One(v) => match most_recent {
|
||||||
|
Some(Date::Year(_)) => Date::Year(v),
|
||||||
|
Some(Date::YearMonth(y, _)) => Date::YearMonth(y, v as u32),
|
||||||
|
Some(Date::Date(d)) => Date::Date(d.clone().with_day(v as u32).unwrap()),
|
||||||
|
None => Date::Year(v),
|
||||||
|
},
|
||||||
|
DateSegment::Two(y, m) => Date::YearMonth(y, m as u32),
|
||||||
|
DateSegment::Three(y, m, d) => {
|
||||||
|
Date::Date(chrono::NaiveDate::from_ymd_opt(y, m as u32, d as u32).unwrap())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dates.push(new_date.clone());
|
||||||
|
most_recent = Some(new_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((input, dates))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_date_segment<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, DateSegment, E> {
|
||||||
|
|input| {
|
||||||
|
let (input, _) = tag(",")(input)?;
|
||||||
|
let (input, element) = parse_date().parse(input)?;
|
||||||
|
|
||||||
|
Ok((input, element))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_date<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, DateSegment, E> {
|
||||||
|
alt((parse_three(), parse_two(), parse_one()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_one<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, DateSegment, E> {
|
||||||
|
parse_number().map(|year| DateSegment::One(year))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_two<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, DateSegment, E> {
|
||||||
|
|input| {
|
||||||
|
let (input, year) = parse_number().parse(input)?;
|
||||||
|
let (input, _) = tag("-")(input)?;
|
||||||
|
let (input, month) = parse_number().parse(input)?;
|
||||||
|
Ok((input, DateSegment::Two(year, month)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_three<'a, E: ParseError<&'a str>>() -> impl Parser<&'a str, DateSegment, E> {
|
||||||
|
|input| {
|
||||||
|
let (input, year) = parse_number().parse(input)?;
|
||||||
|
let (input, _) = tag("-")(input)?;
|
||||||
|
let (input, month) = parse_number().parse(input)?;
|
||||||
|
let (input, _) = tag("-")(input)?;
|
||||||
|
let (input, day) = parse_number().parse(input)?;
|
||||||
|
Ok((input, DateSegment::Three(year, month, day)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1059,3 +1135,58 @@ k<. Hard line breaks are all other linebreaks.",
|
||||||
parse_tree::<nom::error::VerboseError<&str>>(&data).unwrap();
|
parse_tree::<nom::error::VerboseError<&str>>(&data).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod date_test {
|
||||||
|
use super::*;
|
||||||
|
use cool_asserts::assert_matches;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_a_year() {
|
||||||
|
assert_matches!(parse_date_field::<nom::error::VerboseError<&str>>().parse("1996"), Ok((_, date)) => {
|
||||||
|
assert_eq!(date, vec![Date::Year(1996)]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_a_month() {
|
||||||
|
assert_matches!(
|
||||||
|
parse_date_field::<nom::error::VerboseError<&str>>().parse("1996-12"),
|
||||||
|
Ok((_, date)) => assert_eq!(date, vec![Date::YearMonth(1996, 12)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_a_date() {
|
||||||
|
assert_matches!(
|
||||||
|
parse_date_field::<nom::error::VerboseError<&str>>().parse("1996-12-27"),
|
||||||
|
Ok((_, date)) => assert_eq!(date, vec![Date::Date(
|
||||||
|
NaiveDate::from_ymd_opt(1996, 12, 27).unwrap()
|
||||||
|
)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_date_continuation() {
|
||||||
|
assert_matches!(
|
||||||
|
parse_date_field::<nom::error::VerboseError<&str>>().parse("1996-12-27,28"),
|
||||||
|
Ok((_, date)) => assert_eq!(date, vec![
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1996, 12, 27).unwrap()),
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1996, 12, 28).unwrap())
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_date_crossing_year_boundary() {
|
||||||
|
assert_matches!(
|
||||||
|
parse_date_field::<nom::error::VerboseError<&str>>().parse("1996-12-27,28,1997-01-03,04"),
|
||||||
|
Ok((_, date)) => assert_eq!(date, vec![
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1996, 12, 27).unwrap()),
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1996, 12, 28).unwrap()),
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1997, 1, 3).unwrap()),
|
||||||
|
Date::Date(NaiveDate::from_ymd_opt(1997, 1, 4).unwrap()),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue