compact_calendar_cli/
config.rs

1use crate::models::{DateDetail, DateRange};
2use chrono::NaiveDate;
3use serde::Deserialize;
4use std::collections::HashMap;
5
6#[derive(Debug, Deserialize)]
7pub struct CalendarConfig {
8    #[serde(default)]
9    pub dates: HashMap<String, RawDateDetail>,
10    #[serde(default)]
11    pub ranges: Vec<RawDateRange>,
12}
13
14#[derive(Debug, Deserialize, Clone)]
15pub struct RawDateDetail {
16    #[serde(default)]
17    pub description: String,
18    #[serde(default)]
19    pub color: Option<String>,
20}
21
22#[derive(Debug, Deserialize, Clone)]
23pub struct RawDateRange {
24    pub start: String,
25    pub end: String,
26    pub color: String,
27    #[serde(default)]
28    pub description: Option<String>,
29}
30
31impl CalendarConfig {
32    pub fn parse_dates(&self) -> HashMap<NaiveDate, DateDetail> {
33        self.dates
34            .iter()
35            .filter_map(|(date_str, detail)| {
36                NaiveDate::parse_from_str(date_str, "%Y-%m-%d")
37                    .ok()
38                    .map(|date| {
39                        (
40                            date,
41                            DateDetail {
42                                description: detail.description.clone(),
43                                color: detail.color.clone(),
44                            },
45                        )
46                    })
47            })
48            .collect()
49    }
50
51    pub fn parse_dates_for_year(&self, year: i32) -> HashMap<NaiveDate, DateDetail> {
52        self.dates
53            .iter()
54            .flat_map(|(date_str, detail)| {
55                if let Ok(date) = NaiveDate::parse_from_str(date_str, "%Y-%m-%d") {
56                    return vec![(
57                        date,
58                        DateDetail {
59                            description: detail.description.clone(),
60                            color: detail.color.clone(),
61                        },
62                    )];
63                }
64                if let Ok(md) =
65                    chrono::NaiveDate::parse_from_str(&format!("{}-{}", year, date_str), "%Y-%m-%d")
66                {
67                    return vec![(
68                        md,
69                        DateDetail {
70                            description: detail.description.clone(),
71                            color: detail.color.clone(),
72                        },
73                    )];
74                }
75
76                vec![]
77            })
78            .collect()
79    }
80
81    pub fn parse_ranges(&self) -> Vec<DateRange> {
82        self.ranges
83            .iter()
84            .filter_map(|range| {
85                let start = NaiveDate::parse_from_str(&range.start, "%Y-%m-%d").ok()?;
86                let end = NaiveDate::parse_from_str(&range.end, "%Y-%m-%d").ok()?;
87                Some(DateRange {
88                    start,
89                    end,
90                    color: range.color.clone(),
91                    description: range.description.clone(),
92                })
93            })
94            .collect()
95    }
96
97    pub fn parse_ranges_for_year(&self, year: i32) -> Vec<DateRange> {
98        self.ranges
99            .iter()
100            .filter_map(|range| {
101                if let (Ok(start), Ok(end)) = (
102                    NaiveDate::parse_from_str(&range.start, "%Y-%m-%d"),
103                    NaiveDate::parse_from_str(&range.end, "%Y-%m-%d"),
104                ) {
105                    return Some(DateRange {
106                        start,
107                        end,
108                        color: range.color.clone(),
109                        description: range.description.clone(),
110                    });
111                }
112                if let (Ok(start), Ok(end)) = (
113                    NaiveDate::parse_from_str(&format!("{}-{}", year, &range.start), "%Y-%m-%d"),
114                    NaiveDate::parse_from_str(&format!("{}-{}", year, &range.end), "%Y-%m-%d"),
115                ) {
116                    return Some(DateRange {
117                        start,
118                        end,
119                        color: range.color.clone(),
120                        description: range.description.clone(),
121                    });
122                }
123
124                None
125            })
126            .collect()
127    }
128}