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}