git_calver/
calver.rs

1use std::fmt;
2
3use chrono::prelude::Datelike;
4use chrono::prelude::Local;
5use chrono::DateTime;
6
7#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
8pub struct CalVer {
9    year: u16,
10    month: u8,
11    revision: i8,
12}
13
14impl CalVer {
15    pub fn new(revision: i8) -> CalVer {
16        let t: DateTime<Local> = Local::now();
17        CalVer {
18            year: t.year() as u16,
19            month: t.month() as u8,
20            revision,
21        }
22    }
23
24    pub fn zero() -> CalVer {
25        CalVer {
26            year: 0,
27            month: 0,
28            revision: 0,
29        }
30    }
31}
32
33impl fmt::Display for CalVer {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        write!(f, "{}.{}.{}", self.year % 100, self.month, self.revision)
36    }
37}
38
39pub trait ToCalVer {
40    fn calver(&self) -> Option<CalVer>;
41}
42
43impl ToCalVer for String {
44    fn calver(&self) -> Option<CalVer> {
45        let mut chunk_iter = self.splitn(3, '.');
46        let y = chunk_iter.next()?.parse::<u16>().ok()?;
47        let y = if y >= 100 { y } else { y + 2000 };
48        let m = chunk_iter.next()?.parse::<u8>().ok()?;
49        let r = chunk_iter.next()?.parse::<i8>().ok()?;
50        Some(CalVer {
51            year: y,
52            month: m,
53            revision: r,
54        })
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn string_to_calver() {
64        assert_eq!(
65            String::from("20.2.1").calver().unwrap(),
66            CalVer {
67                year: 2020,
68                month: 2,
69                revision: 1,
70            }
71        );
72        assert_eq!(
73            String::from("2020.2.1").calver().unwrap(),
74            CalVer {
75                year: 2020,
76                month: 2,
77                revision: 1,
78            }
79        );
80        assert_eq!(String::from("v0.1").calver(), None);
81    }
82}