Skip to main content

todo_txt/task/
period.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3pub enum Period {
4    Day,
5    Week,
6    Month,
7    Year,
8}
9
10impl Period {
11    fn is_leap_year(year: i32) -> bool {
12        year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
13    }
14
15    pub fn days_in_month(month: u32, year: i32) -> u32 {
16        if month == 2 {
17            if Self::is_leap_year(year) { 29 } else { 28 }
18        } else if [1, 3, 5, 7, 8, 10, 12].contains(&month) {
19            31
20        } else {
21            30
22        }
23    }
24}
25
26impl std::str::FromStr for Period {
27    type Err = crate::Error;
28
29    fn from_str(s: &str) -> Result<Self, Self::Err> {
30        use Period::*;
31
32        match s {
33            "d" => Ok(Day),
34            "w" => Ok(Week),
35            "m" => Ok(Month),
36            "y" => Ok(Year),
37            _ => Err(crate::Error::InvalidPeriod(s.to_string())),
38        }
39    }
40}
41
42impl std::fmt::Display for Period {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        use Period::*;
45
46        let s = match *self {
47            Day => "d",
48            Week => "w",
49            Month => "m",
50            Year => "y",
51        };
52
53        f.write_str(s)?;
54
55        Ok(())
56    }
57}
58
59impl std::ops::Add<chrono::NaiveDate> for Period {
60    type Output = chrono::NaiveDate;
61
62    fn add(self, rhs: Self::Output) -> Self::Output {
63        let rec = super::Recurrence {
64            num: 1,
65            period: self,
66            strict: true,
67        };
68        rec + rhs
69    }
70}