oparl_types/
date.rs

1// SPDX-FileCopyrightText: Politik im Blick developers
2// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2
5
6use std::{fmt::Display, str::FromStr};
7
8#[derive(
9    Debug,
10    Clone,
11    PartialEq,
12    Eq,
13    PartialOrd,
14    Ord,
15    Hash,
16    derive_more::AsRef,
17    derive_more::From,
18    derive_more::Into,
19    serde_with::SerializeDisplay,
20    serde_with::DeserializeFromStr,
21)]
22#[cfg_attr(feature = "sea-orm", derive(sea_orm::DeriveValueType))]
23pub struct Date(time::Date);
24
25impl FromStr for Date {
26    type Err = time::error::Parse;
27
28    fn from_str(s: &str) -> Result<Self, Self::Err> {
29        use time::format_description::well_known::Iso8601;
30
31        Ok(Self(time::Date::parse(s, &Iso8601::DEFAULT)?))
32    }
33}
34
35impl Display for Date {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        use time::format_description::well_known::Iso8601;
38
39        write!(f, "{}", self.0.format(&Iso8601::DATE).expect("valid date"))
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::Date;
46
47    use time::macros::date;
48
49    #[test]
50    fn from_str() {
51        let parsed: Date = "2025-01-07"
52            .parse()
53            .expect("string must be parseable as Date");
54        assert_eq!(parsed, Date(date!(2025 - 01 - 07)));
55    }
56
57    #[test]
58    fn to_string() {
59        let d = Date(date!(2025 - 01 - 07));
60
61        assert_eq!(d.to_string(), "2025-01-07".to_string());
62    }
63}
64
65#[cfg(test)]
66mod serde_tests {
67    use super::Date;
68
69    use pretty_assertions::assert_eq;
70    use serde_json::json;
71    use time::macros::date;
72
73    #[test]
74    fn serialize() {
75        assert_eq!(json!(Date(date!(2025 - 01 - 07))), json!("2025-01-07"));
76    }
77
78    #[test]
79    fn deserialize_good() {
80        let deserialized: Date =
81            serde_json::from_value(json!("2025-01-07")).expect("json must be parseable as Date");
82
83        assert_eq!(deserialized, Date(date!(2025 - 01 - 07)));
84    }
85
86    #[test]
87    fn deserialize_bad() {
88        assert!(serde_json::from_value::<Date>(json!("xyzabcd")).is_err());
89        assert!(serde_json::from_value::<Date>(json!(true)).is_err());
90        assert!(serde_json::from_value::<Date>(json!(123)).is_err());
91    }
92}