azure_core/date/
iso8601.rs
1use crate::error::{ErrorKind, ResultExt};
2use serde::{de, Deserialize, Deserializer, Serializer};
3use time::{
4 format_description::well_known::{
5 iso8601::{Config, EncodedConfig, TimePrecision},
6 Iso8601,
7 },
8 OffsetDateTime, UtcOffset,
9};
10
11const SERDE_CONFIG: EncodedConfig = Config::DEFAULT
12 .set_year_is_six_digits(false)
13 .set_time_precision(TimePrecision::Second {
14 decimal_digits: None,
15 })
16 .encode();
17
18pub fn parse_iso8601(s: &str) -> crate::Result<OffsetDateTime> {
19 OffsetDateTime::parse(s, &Iso8601::<SERDE_CONFIG>)
20 .with_context(ErrorKind::DataConversion, || {
21 format!("unable to parse iso8601 date '{s}")
22 })
23}
24
25pub fn to_iso8601(date: &OffsetDateTime) -> crate::Result<String> {
26 date.format(&Iso8601::<SERDE_CONFIG>)
27 .with_context(ErrorKind::DataConversion, || {
28 format!("unable to format date '{date:?}")
29 })
30}
31
32pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
33where
34 D: Deserializer<'de>,
35{
36 let s = String::deserialize(deserializer)?;
37 parse_iso8601(&s).map_err(de::Error::custom)
38}
39
40pub fn serialize<S>(date: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
41where
42 S: Serializer,
43{
44 date.to_offset(UtcOffset::UTC);
45 let as_str = to_iso8601(date).map_err(serde::ser::Error::custom)?;
46 serializer.serialize_str(&as_str)
47}
48
49pub mod option {
50 use crate::date::iso8601::{parse_iso8601, to_iso8601};
51 use serde::{Deserialize, Deserializer, Serializer};
52 use time::OffsetDateTime;
53
54 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
55 where
56 D: Deserializer<'de>,
57 {
58 let s: Option<String> = Option::deserialize(deserializer)?;
59 s.map(|s| parse_iso8601(&s).map_err(serde::de::Error::custom))
60 .transpose()
61 }
62
63 pub fn serialize<S>(date: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
64 where
65 S: Serializer,
66 {
67 if let Some(date) = date {
68 serializer.serialize_str(&to_iso8601(date).map_err(serde::ser::Error::custom)?)
69 } else {
70 serializer.serialize_none()
71 }
72 }
73}