acari_lib/
query.rs

1use crate::error::AcariError;
2use chrono::{Local, NaiveDate};
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Day {
7  Today,
8  Yesterday,
9  Date(NaiveDate),
10}
11
12impl Day {
13  pub fn as_date(self) -> NaiveDate {
14    match self {
15      Day::Today => Local::now().naive_local().date(),
16      Day::Yesterday => Local::now().naive_local().date().pred(),
17      Day::Date(date) => date,
18    }
19  }
20}
21
22impl FromStr for Day {
23  type Err = AcariError;
24
25  fn from_str(s: &str) -> Result<Self, Self::Err> {
26    match s.to_lowercase().as_str() {
27      "today" | "now" => Ok(Day::Today),
28      "yesterday" => Ok(Day::Yesterday),
29      date => Ok(Day::Date(NaiveDate::parse_from_str(date, "%Y-%m-%d")?)),
30    }
31  }
32}
33
34impl From<NaiveDate> for Day {
35  fn from(date: NaiveDate) -> Self {
36    Day::Date(date)
37  }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum DateSpan {
42  ThisWeek,
43  LastWeek,
44  ThisMonth,
45  LastMonth,
46  Day(Day),
47  FromTo(NaiveDate, NaiveDate),
48}
49
50impl FromStr for DateSpan {
51  type Err = AcariError;
52
53  fn from_str(s: &str) -> Result<Self, Self::Err> {
54    match s.to_lowercase().as_str() {
55      "this-week" | "week" => Ok(DateSpan::ThisWeek),
56      "last-week" => Ok(DateSpan::LastWeek),
57      "this-month" | "month" => Ok(DateSpan::ThisMonth),
58      "last-month" => Ok(DateSpan::LastMonth),
59      date_or_range => match date_or_range.find('/') {
60        Some(idx) => Ok(DateSpan::FromTo(
61          NaiveDate::parse_from_str(&date_or_range[..idx], "%Y-%m-%d")?,
62          NaiveDate::parse_from_str(&date_or_range[idx + 1..], "%Y-%m-%d")?,
63        )),
64        None => Ok(DateSpan::Day(date_or_range.parse()?)),
65      },
66    }
67  }
68}
69
70impl From<Day> for DateSpan {
71  fn from(day: Day) -> Self {
72    DateSpan::Day(day)
73  }
74}
75
76impl From<NaiveDate> for DateSpan {
77  fn from(date: NaiveDate) -> Self {
78    DateSpan::Day(Day::Date(date))
79  }
80}
81
82#[cfg(test)]
83mod tests {
84  use super::*;
85  use chrono::NaiveDate;
86  use pretty_assertions::assert_eq;
87
88  #[test]
89  fn test_parse_day() -> Result<(), Box<dyn std::error::Error>> {
90    assert_eq!(Day::Today, "today".parse()?);
91    assert_eq!(Day::Today, "now".parse()?);
92    assert_eq!(Day::Yesterday, "yesterday".parse()?);
93    assert_eq!(Day::Date(NaiveDate::from_ymd(2020, 3, 4)), "2020-03-04".parse()?);
94
95    Ok(())
96  }
97
98  #[test]
99  fn test_parse_datespan() -> Result<(), Box<dyn std::error::Error>> {
100    assert_eq!(DateSpan::Day(Day::Today), "today".parse()?);
101    assert_eq!(DateSpan::Day(Day::Today), "now".parse()?);
102    assert_eq!(DateSpan::Day(Day::Yesterday), "yesterday".parse()?);
103    assert_eq!(DateSpan::Day(Day::Date(NaiveDate::from_ymd(2020, 3, 4))), "2020-03-04".parse()?);
104    assert_eq!(DateSpan::ThisWeek, "this-week".parse()?);
105    assert_eq!(DateSpan::LastWeek, "last-week".parse()?);
106    assert_eq!(DateSpan::ThisMonth, "this-month".parse()?);
107    assert_eq!(DateSpan::LastMonth, "last-month".parse()?);
108
109    Ok(())
110  }
111}