1use std::{fmt::Display, str::FromStr};
7
8use time::OffsetDateTime;
9
10use crate::DateTime;
11
12#[derive(
13 Debug,
14 Clone,
15 PartialEq,
16 Eq,
17 PartialOrd,
18 Ord,
19 Hash,
20 derive_more::AsRef,
21 derive_more::From,
22 derive_more::Into,
23 serde_with::SerializeDisplay,
24 serde_with::DeserializeFromStr,
25)]
26#[cfg_attr(feature = "sea-orm", derive(sea_orm::DeriveValueType))]
27pub struct Date(time::Date);
28
29impl FromStr for Date {
30 type Err = time::error::Parse;
31
32 fn from_str(s: &str) -> Result<Self, Self::Err> {
33 use time::format_description::well_known::Iso8601;
34
35 Ok(Self(time::Date::parse(s, &Iso8601::DEFAULT)?))
36 }
37}
38
39impl Display for Date {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 use time::format_description::well_known::Iso8601;
42
43 write!(f, "{}", self.0.format(&Iso8601::DATE).expect("valid date"))
44 }
45}
46
47impl From<DateTime> for Date {
48 fn from(value: DateTime) -> Self {
49 Self(OffsetDateTime::from(value).date())
50 }
51}
52
53#[cfg(feature = "sea-orm")]
54mod sea_orm_impls {
55 use sea_orm::{ActiveValue, IntoActiveValue};
56
57 use super::Date;
58
59 impl IntoActiveValue<Date> for Date {
60 fn into_active_value(self) -> ActiveValue<Date> {
61 ActiveValue::Set(self)
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use time::macros::date;
69
70 use super::Date;
71
72 #[test]
73 fn from_str() {
74 let parsed: Date = "2025-01-07"
75 .parse()
76 .expect("string must be parseable as Date");
77 assert_eq!(parsed, Date(date!(2025 - 01 - 07)));
78 }
79
80 #[test]
81 fn to_string() {
82 let d = Date(date!(2025 - 01 - 07));
83
84 assert_eq!(d.to_string(), "2025-01-07".to_string());
85 }
86}
87
88#[cfg(test)]
89mod serde_tests {
90 use pretty_assertions::assert_eq;
91 use serde_json::json;
92 use time::macros::date;
93
94 use super::Date;
95
96 #[test]
97 fn serialize() {
98 assert_eq!(json!(Date(date!(2025 - 01 - 07))), json!("2025-01-07"));
99 }
100
101 #[test]
102 fn deserialize_good() {
103 let deserialized: Date =
104 serde_json::from_value(json!("2025-01-07")).expect("json must be parseable as Date");
105
106 assert_eq!(deserialized, Date(date!(2025 - 01 - 07)));
107 }
108
109 #[test]
110 fn deserialize_bad() {
111 assert!(serde_json::from_value::<Date>(json!("xyzabcd")).is_err());
112 assert!(serde_json::from_value::<Date>(json!(true)).is_err());
113 assert!(serde_json::from_value::<Date>(json!(123)).is_err());
114 }
115}