rweather_decoder/
datetime.rs

1//! Module for handling UTC date and time representations.
2
3use anyhow::Result;
4use chrono::{NaiveTime, NaiveDateTime};
5use serde::{de, Serialize, Deserialize, Deserializer, ser::SerializeTuple};
6
7const UTC_DATE_TIME_FORMAT: &str = "%Y-%m-%dT%H:%M:%SZ";
8const UTC_TIME_FORMAT: &str = "%H:%M:%SZ";
9
10/// Wrapper for UTC-based [`NaiveDateTime`].
11///
12/// Example JSON representation:
13/// ```json
14/// "2023-12-27T08:30:00Z"
15/// ```
16#[non_exhaustive]
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct UtcDateTime(pub NaiveDateTime);
19
20impl Serialize for UtcDateTime {
21    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22    where
23        S: serde::Serializer,
24    {
25        serializer.serialize_str(&self.0.format(UTC_DATE_TIME_FORMAT).to_string())
26    }
27}
28
29impl<'de> Deserialize<'de> for UtcDateTime {
30    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31    where
32        D: Deserializer<'de>,
33    {
34        Ok(Self(NaiveDateTime::parse_from_str(&String::deserialize(deserializer)?, UTC_DATE_TIME_FORMAT)
35            .map_err(de::Error::custom)?))
36    }
37}
38
39/// Wrapper for integer day and UTC-based [`NaiveTime`].
40///
41/// Example JSON representation:
42/// ```json
43/// [27, "08:30:00Z"]
44/// ```
45#[non_exhaustive]
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub struct UtcDayTime(pub u32, pub NaiveTime);
48
49impl Serialize for UtcDayTime {
50    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
51    where
52        S: serde::Serializer,
53    {
54        let time = self.1.format(UTC_TIME_FORMAT).to_string();
55
56        let mut tup = serializer.serialize_tuple(2)?;
57        tup.serialize_element(&self.0)?;
58        tup.serialize_element(&time)?;
59        tup.end()
60    }
61}
62
63impl<'de> Deserialize<'de> for UtcDayTime {
64    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
65    where
66        D: Deserializer<'de>,
67    {
68        let (d, time) = <(u32, String)>::deserialize(deserializer)?;
69        let nt = NaiveTime::parse_from_str(&time, UTC_TIME_FORMAT)
70            .map_err(de::Error::custom)?;
71
72        Ok(Self(d, nt))
73    }
74}
75
76/// Wrapper for UTC-based [`NaiveTime`].
77///
78/// Example JSON representation:
79/// ```json
80/// "08:30:00Z"
81/// ```
82#[non_exhaustive]
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub struct UtcTime(pub NaiveTime);
85
86impl Serialize for UtcTime {
87    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
88    where
89        S: serde::Serializer,
90    {
91        serializer.serialize_str(&self.0.format(UTC_TIME_FORMAT).to_string())
92    }
93}
94
95impl<'de> Deserialize<'de> for UtcTime {
96    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
97    where
98        D: Deserializer<'de>,
99    {
100        let s = String::deserialize(deserializer)?;
101        Ok(Self(NaiveTime::parse_from_str(&s, UTC_TIME_FORMAT).map_err(de::Error::custom)?))
102    }
103}