1#![warn(clippy::as_conversions)]
14
15use crate::{
16 formats::{Flexible, Format, Strict, Strictness},
17 prelude::*,
18 utils::duration::{use_duration_signed_de, use_duration_signed_ser},
19};
20#[cfg(feature = "std")]
21use ::time_0_3::format_description::well_known::{
22 iso8601::EncodedConfig, Iso8601, Rfc2822, Rfc3339,
23};
24use ::time_0_3::{Duration as Time03Duration, OffsetDateTime, PrimitiveDateTime};
25
26fn unix_epoch_primitive() -> PrimitiveDateTime {
28 PrimitiveDateTime::new(
29 ::time_0_3::Date::from_ordinal_date(1970, 1).unwrap(),
30 ::time_0_3::Time::from_hms_nano(0, 0, 0, 0).unwrap(),
31 )
32}
33
34fn duration_into_duration_signed(dur: &Time03Duration) -> DurationSigned {
36 let std_dur = Duration::new(
37 dur.whole_seconds().unsigned_abs(),
38 dur.subsec_nanoseconds().unsigned_abs(),
39 );
40
41 DurationSigned::with_duration(
42 if dur.is_negative() {
44 Sign::Negative
45 } else {
46 Sign::Positive
47 },
48 std_dur,
49 )
50}
51
52fn offset_datetime_to_duration(source: &OffsetDateTime) -> DurationSigned {
53 duration_into_duration_signed(&(*source - OffsetDateTime::UNIX_EPOCH))
54}
55
56fn primitive_datetime_to_duration(source: &PrimitiveDateTime) -> DurationSigned {
57 duration_into_duration_signed(&(*source - unix_epoch_primitive()))
58}
59
60impl<STRICTNESS> SerializeAs<Time03Duration> for
DurationNanoSeconds<String, STRICTNESS> where STRICTNESS: Strictness {
fn serialize_as<S>(source: &Time03Duration, serializer: S)
-> Result<S::Ok, S::Error> where S: Serializer {
let dur: DurationSigned = duration_into_duration_signed(source);
DurationNanoSeconds::<String,
STRICTNESS>::serialize_as(&dur, serializer)
}
}use_duration_signed_ser!(
62 DurationSeconds DurationSeconds,
63 DurationMilliSeconds DurationMilliSeconds,
64 DurationMicroSeconds DurationMicroSeconds,
65 DurationNanoSeconds DurationNanoSeconds,
66 => {
67 Time03Duration; duration_into_duration_signed =>
68 {i64, STRICTNESS => STRICTNESS: Strictness}
69 {f64, STRICTNESS => STRICTNESS: Strictness}
70 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
71 }
72);
73
74impl<STRICTNESS> SerializeAs<PrimitiveDateTime> for
TimestampNanoSeconds<String, STRICTNESS> where STRICTNESS: Strictness {
fn serialize_as<S>(source: &PrimitiveDateTime, serializer: S)
-> Result<S::Ok, S::Error> where S: Serializer {
let dur: DurationSigned = primitive_datetime_to_duration(source);
DurationNanoSeconds::<String,
STRICTNESS>::serialize_as(&dur, serializer)
}
}use_duration_signed_ser!(
75 TimestampSeconds DurationSeconds,
76 TimestampMilliSeconds DurationMilliSeconds,
77 TimestampMicroSeconds DurationMicroSeconds,
78 TimestampNanoSeconds DurationNanoSeconds,
79 => {
80 OffsetDateTime; offset_datetime_to_duration =>
81 {i64, STRICTNESS => STRICTNESS: Strictness}
82 {f64, STRICTNESS => STRICTNESS: Strictness}
83 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
84 }
85 => {
86 PrimitiveDateTime; primitive_datetime_to_duration =>
87 {i64, STRICTNESS => STRICTNESS: Strictness}
88 {f64, STRICTNESS => STRICTNESS: Strictness}
89 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
90 }
91);
92
93impl<STRICTNESS> SerializeAs<Time03Duration> for
DurationNanoSecondsWithFrac<String, STRICTNESS> where
STRICTNESS: Strictness {
fn serialize_as<S>(source: &Time03Duration, serializer: S)
-> Result<S::Ok, S::Error> where S: Serializer {
let dur: DurationSigned = duration_into_duration_signed(source);
DurationNanoSecondsWithFrac::<String,
STRICTNESS>::serialize_as(&dur, serializer)
}
}use_duration_signed_ser!(
95 DurationSecondsWithFrac DurationSecondsWithFrac,
96 DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
97 DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
98 DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
99 => {
100 Time03Duration; duration_into_duration_signed =>
101 {f64, STRICTNESS => STRICTNESS: Strictness}
102 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
103 }
104);
105
106impl<STRICTNESS> SerializeAs<PrimitiveDateTime> for
TimestampNanoSecondsWithFrac<String, STRICTNESS> where
STRICTNESS: Strictness {
fn serialize_as<S>(source: &PrimitiveDateTime, serializer: S)
-> Result<S::Ok, S::Error> where S: Serializer {
let dur: DurationSigned = primitive_datetime_to_duration(source);
DurationNanoSecondsWithFrac::<String,
STRICTNESS>::serialize_as(&dur, serializer)
}
}use_duration_signed_ser!(
107 TimestampSecondsWithFrac DurationSecondsWithFrac,
108 TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac,
109 TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac,
110 TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac,
111 => {
112 OffsetDateTime; offset_datetime_to_duration =>
113 {f64, STRICTNESS => STRICTNESS: Strictness}
114 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
115 }
116 => {
117 PrimitiveDateTime; primitive_datetime_to_duration =>
118 {f64, STRICTNESS => STRICTNESS: Strictness}
119 #[cfg(feature = "alloc")] {String, STRICTNESS => STRICTNESS: Strictness}
120 }
121);
122
123fn duration_from_duration_signed<'de, D>(sdur: DurationSigned) -> Result<Time03Duration, D::Error>
125where
126 D: Deserializer<'de>,
127{
128 let mut dur: Time03Duration = match sdur.duration.try_into() {
129 Ok(dur) => dur,
130 Err(msg) => {
131 return Err(DeError::custom(format_args!("Duration is outside of the representable range: {0}", msg)format_args!(
132 "Duration is outside of the representable range: {msg}"
133 )))
134 }
135 };
136 if sdur.sign.is_negative() {
137 dur = -dur;
138 }
139 Ok(dur)
140}
141
142fn duration_to_offset_datetime<'de, D>(dur: DurationSigned) -> Result<OffsetDateTime, D::Error>
143where
144 D: Deserializer<'de>,
145{
146 Ok(OffsetDateTime::UNIX_EPOCH + duration_from_duration_signed::<D>(dur)?)
147}
148
149fn duration_to_primitive_datetime<'de, D>(
150 dur: DurationSigned,
151) -> Result<PrimitiveDateTime, D::Error>
152where
153 D: Deserializer<'de>,
154{
155 Ok(unix_epoch_primitive() + duration_from_duration_signed::<D>(dur)?)
156}
157
158impl<'de> DeserializeAs<'de, Time03Duration> for
DurationNanoSeconds<f64, Strict> where {
fn deserialize_as<D>(deserializer: D) -> Result<Time03Duration, D::Error>
where D: Deserializer<'de> {
let dur: DurationSigned =
DurationNanoSeconds::<f64, Strict>::deserialize_as(deserializer)?;
duration_from_duration_signed::<D>(dur)
}
}use_duration_signed_de!(
160 DurationSeconds DurationSeconds,
161 DurationMilliSeconds DurationMilliSeconds,
162 DurationMicroSeconds DurationMicroSeconds,
163 DurationNanoSeconds DurationNanoSeconds,
164 => {
165 Time03Duration; duration_from_duration_signed =>
166 {FORMAT, Flexible => FORMAT: Format}
167 {i64, Strict =>}
168 #[cfg(feature = "alloc")] {String, Strict =>}
169 #[cfg(feature = "std")] {f64, Strict =>}
170 }
171);
172
173impl<'de> DeserializeAs<'de, PrimitiveDateTime> for
TimestampNanoSeconds<f64, Strict> where {
fn deserialize_as<D>(deserializer: D)
-> Result<PrimitiveDateTime, D::Error> where D: Deserializer<'de> {
let dur: DurationSigned =
DurationNanoSeconds::<f64, Strict>::deserialize_as(deserializer)?;
duration_to_primitive_datetime::<D>(dur)
}
}use_duration_signed_de!(
174 TimestampSeconds DurationSeconds,
175 TimestampMilliSeconds DurationMilliSeconds,
176 TimestampMicroSeconds DurationMicroSeconds,
177 TimestampNanoSeconds DurationNanoSeconds,
178 => {
179 OffsetDateTime; duration_to_offset_datetime =>
180 {FORMAT, Flexible => FORMAT: Format}
181 {i64, Strict =>}
182 #[cfg(feature = "alloc")] {String, Strict =>}
183 #[cfg(feature = "std")] {f64, Strict =>}
184 }
185 => {
186 PrimitiveDateTime; duration_to_primitive_datetime =>
187 {FORMAT, Flexible => FORMAT: Format}
188 {i64, Strict =>}
189 #[cfg(feature = "alloc")] {String, Strict =>}
190 #[cfg(feature = "std")] {f64, Strict =>}
191 }
192);
193
194impl<'de> DeserializeAs<'de, Time03Duration> for
DurationNanoSecondsWithFrac<String, Strict> where {
fn deserialize_as<D>(deserializer: D) -> Result<Time03Duration, D::Error>
where D: Deserializer<'de> {
let dur: DurationSigned =
DurationNanoSecondsWithFrac::<String,
Strict>::deserialize_as(deserializer)?;
duration_from_duration_signed::<D>(dur)
}
}use_duration_signed_de!(
196 DurationSecondsWithFrac DurationSecondsWithFrac,
197 DurationMilliSecondsWithFrac DurationMilliSecondsWithFrac,
198 DurationMicroSecondsWithFrac DurationMicroSecondsWithFrac,
199 DurationNanoSecondsWithFrac DurationNanoSecondsWithFrac,
200 => {
201 Time03Duration; duration_from_duration_signed =>
202 {FORMAT, Flexible => FORMAT: Format}
203 {f64, Strict =>}
204 #[cfg(feature = "alloc")] {String, Strict =>}
205 }
206);
207
208impl<'de> DeserializeAs<'de, PrimitiveDateTime> for
TimestampNanoSecondsWithFrac<String, Strict> where {
fn deserialize_as<D>(deserializer: D)
-> Result<PrimitiveDateTime, D::Error> where D: Deserializer<'de> {
let dur: DurationSigned =
DurationNanoSecondsWithFrac::<String,
Strict>::deserialize_as(deserializer)?;
duration_to_primitive_datetime::<D>(dur)
}
}use_duration_signed_de!(
209 TimestampSecondsWithFrac DurationSecondsWithFrac,
210 TimestampMilliSecondsWithFrac DurationMilliSecondsWithFrac,
211 TimestampMicroSecondsWithFrac DurationMicroSecondsWithFrac,
212 TimestampNanoSecondsWithFrac DurationNanoSecondsWithFrac,
213 => {
214 OffsetDateTime; duration_to_offset_datetime =>
215 {FORMAT, Flexible => FORMAT: Format}
216 {f64, Strict =>}
217 #[cfg(feature = "alloc")] {String, Strict =>}
218 }
219 => {
220 PrimitiveDateTime; duration_to_primitive_datetime =>
221 {FORMAT, Flexible => FORMAT: Format}
222 {f64, Strict =>}
223 #[cfg(feature = "alloc")] {String, Strict =>}
224 }
225);
226
227#[cfg(feature = "std")]
228impl SerializeAs<OffsetDateTime> for Rfc2822 {
229 fn serialize_as<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
230 where
231 S: Serializer,
232 {
233 datetime
234 .format(&Rfc2822)
235 .map_err(S::Error::custom)?
236 .serialize(serializer)
237 }
238}
239
240#[cfg(feature = "std")]
241impl<'de> DeserializeAs<'de, OffsetDateTime> for Rfc2822 {
242 fn deserialize_as<D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
243 where
244 D: Deserializer<'de>,
245 {
246 struct Helper;
247 impl Visitor<'_> for Helper {
248 type Value = OffsetDateTime;
249
250 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
251 formatter.write_str("a RFC2822-formatted `OffsetDateTime`")
252 }
253
254 fn visit_str<E: DeError>(self, value: &str) -> Result<Self::Value, E> {
255 Self::Value::parse(value, &Rfc2822).map_err(E::custom)
256 }
257 }
258
259 deserializer.deserialize_str(Helper)
260 }
261}
262
263#[cfg(feature = "std")]
264impl SerializeAs<OffsetDateTime> for Rfc3339 {
265 fn serialize_as<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
266 where
267 S: Serializer,
268 {
269 datetime
270 .format(&Rfc3339)
271 .map_err(S::Error::custom)?
272 .serialize(serializer)
273 }
274}
275
276#[cfg(feature = "std")]
277impl<'de> DeserializeAs<'de, OffsetDateTime> for Rfc3339 {
278 fn deserialize_as<D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
279 where
280 D: Deserializer<'de>,
281 {
282 struct Helper;
283 impl Visitor<'_> for Helper {
284 type Value = OffsetDateTime;
285
286 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
287 formatter.write_str("a RFC3339-formatted `OffsetDateTime`")
288 }
289
290 fn visit_str<E: DeError>(self, value: &str) -> Result<Self::Value, E> {
291 Self::Value::parse(value, &Rfc3339).map_err(E::custom)
292 }
293 }
294
295 deserializer.deserialize_str(Helper)
296 }
297}
298
299#[cfg(feature = "std")]
300impl<const CONFIG: EncodedConfig> SerializeAs<OffsetDateTime> for Iso8601<CONFIG> {
301 fn serialize_as<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
302 where
303 S: Serializer,
304 {
305 datetime
306 .format(&Iso8601::<CONFIG>)
307 .map_err(S::Error::custom)?
308 .serialize(serializer)
309 }
310}
311
312#[cfg(feature = "std")]
313impl<'de, const CONFIG: EncodedConfig> DeserializeAs<'de, OffsetDateTime> for Iso8601<CONFIG> {
314 fn deserialize_as<D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
315 where
316 D: Deserializer<'de>,
317 {
318 struct Helper<const CONFIG: EncodedConfig>;
319 impl<const CONFIG: EncodedConfig> Visitor<'_> for Helper<CONFIG> {
320 type Value = OffsetDateTime;
321
322 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
323 formatter.write_str("a ISO8601-formatted `OffsetDateTime`")
324 }
325
326 fn visit_str<E: DeError>(self, value: &str) -> Result<Self::Value, E> {
327 Self::Value::parse(value, &Iso8601::<CONFIG>).map_err(E::custom)
328 }
329 }
330
331 deserializer.deserialize_str(Helper::<CONFIG>)
332 }
333}