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}