cses_rs/v1/
time.rs

1use std::{
2    fmt::{self, Display, Formatter},
3    ops::{Add, Sub},
4};
5
6use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
7
8/// 时间类
9/// 24 * 60 * 60
10#[derive(Debug, Eq, PartialEq, Clone, Copy)]
11pub struct Time(i64);
12
13impl Time {
14    /// 新建时间
15    /// h:小时
16    /// m:分钟
17    /// s:秒
18    /// 当分钟和秒大于 60 会自动进位,小于 60 会自动退位
19    pub fn new(h: i64, m: i64, s: i64) -> Self {
20        Time(h * 60 * 60 + m * 60 + s)
21    }
22
23    pub fn h(&self) -> i64 {
24        self.0 / 60 / 60
25    }
26
27    pub fn m(&self) -> i64 {
28        self.0 / 60 % 60
29    }
30
31    pub fn s(&self) -> i64 {
32        self.0 % 60
33    }
34}
35
36impl Display for Time {
37    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
38        let neg = if self.0 < 0 { "-" } else { "" };
39        write!(
40            f,
41            "{}{:02}:{:02}:{:02}",
42            neg,
43            self.h().abs(),
44            self.m().abs(),
45            self.s().abs()
46        )
47    }
48}
49
50impl Serialize for Time {
51    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52    where
53        S: Serializer,
54    {
55        serializer.serialize_str(&self.to_string())
56    }
57}
58
59impl<'de> Deserialize<'de> for Time {
60    fn deserialize<D>(deserializer: D) -> Result<Time, D::Error>
61    where
62        D: Deserializer<'de>,
63    {
64        fn parse_num<'de, D>(it: &str) -> Result<i64, D::Error>
65        where
66            D: Deserializer<'de>,
67        {
68            it.parse()
69                .map_err(|_| de::Error::invalid_type(de::Unexpected::Str(it), &"an integer"))
70        }
71        let s = String::deserialize(deserializer)?;
72        let is_neg = s.starts_with('-');
73        let s = if !is_neg {
74            s
75        } else {
76            s.chars()
77                .enumerate()
78                .filter(|(i, _)| *i != 0)
79                .map(|(_, v)| v)
80                .collect::<String>()
81        };
82        let v: Vec<&str> = s.split(':').collect();
83        let len = v.len();
84        if len != 3 {
85            return Err(de::Error::invalid_length(len, &"time's must be HH:mm:ss"));
86        }
87        let h = parse_num::<D>(v[0])?;
88        let m = parse_num::<D>(v[1])?;
89        let s = parse_num::<D>(v[2])?;
90        let t = h * 60 * 60 + m * 60 + s;
91        let o = if is_neg { Time(-t) } else { Time(t) };
92        Ok(o)
93    }
94}
95
96impl Add for Time {
97    fn add(self, rhs: Self) -> Self::Output {
98        Time(self.0 + rhs.0)
99    }
100
101    type Output = Time;
102}
103
104impl Sub for Time {
105    type Output = Time;
106
107    fn sub(self, rhs: Self) -> Self::Output {
108        Time(self.0 - rhs.0)
109    }
110}
111
112#[cfg(test)]
113mod test {
114    use super::*;
115
116    #[test]
117    fn test_time() {
118        let t = Time::new(1, 2, 3);
119        assert_eq!(t.h(), 1);
120        assert_eq!(t.m(), 2);
121        assert_eq!(t.s(), 3);
122        assert_eq!(t.to_string(), "01:02:03");
123    }
124
125    #[test]
126    fn test_neg_time() {
127        let t = Time::new(0, -1, -2);
128        assert_eq!(t.h(), 0);
129        assert_eq!(t.m(), -1);
130        assert_eq!(t.s(), -2);
131        assert_eq!(t.to_string(), "-00:01:02")
132    }
133
134    #[test]
135    fn test_time_serde() {
136        let t = Time::new(0, 2, 3);
137        let s = serde_json::to_string(&t).unwrap();
138        assert_eq!(s, "\"00:02:03\"");
139        let t2: Time = serde_json::from_str(&s).unwrap();
140        assert_eq!(t, t2);
141    }
142
143    #[test]
144    fn test_time_serde_neg() {
145        let t = Time::new(-1, -2, -3);
146        let s = serde_json::to_string(&t).unwrap();
147        assert_eq!(s, "\"-01:02:03\"");
148        let t2: Time = serde_json::from_str(&s).unwrap();
149        assert_eq!(t, t2);
150    }
151
152    #[test]
153    fn test_time_add() {
154        let t1 = Time::new(1, 2, 3);
155        let t2 = Time::new(4, 5, 6);
156        let t3 = t1 + t2;
157        assert_eq!(t3.h(), 5);
158        assert_eq!(t3.m(), 7);
159        assert_eq!(t3.s(), 9);
160    }
161
162    #[test]
163    fn test_time_sub() {
164        let t1 = Time::new(1, 2, 3);
165        let t2 = Time::new(4, 5, 6);
166        let t3 = t1 - t2;
167        assert_eq!(t3.h(), -3);
168        assert_eq!(t3.m(), -3);
169        assert_eq!(t3.s(), -3);
170    }
171}