am_api/utils/
year_or_date.rs1use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6use time::format_description::FormatItem;
7use time::macros::format_description;
8use time::Date;
9
10pub(crate) const FORMAT: &[FormatItem] = format_description!("[year]-[month]-[day]");
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum YearOrDate {
15 Year(i16),
17 Date(Date),
19}
20
21impl Display for YearOrDate {
22 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23 match self {
24 YearOrDate::Year(year) => write!(f, "{:4}", year),
25 YearOrDate::Date(e) => Display::fmt(e, f),
26 }
27 }
28}
29
30impl Serialize for YearOrDate {
31 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32 where
33 S: Serializer,
34 {
35 match self {
36 YearOrDate::Year(year) => serializer.serialize_str(&year.to_string()),
37 YearOrDate::Date(date) => Serialize::serialize(date, serializer),
38 }
39 }
40}
41
42impl<'de> Deserialize<'de> for YearOrDate {
43 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
44 where
45 D: Deserializer<'de>,
46 {
47 let s: String = Deserialize::deserialize(deserializer)?;
48
49 Ok(match s.contains('-') {
50 false => YearOrDate::Year(i16::from_str(&s).map_err(serde::de::Error::custom)?),
51 true => YearOrDate::Date(Date::parse(&s, &FORMAT).map_err(serde::de::Error::custom)?),
52 })
53 }
54}