async_proto/impls/
chrono.rs

1use {
2    chrono::{
3        offset::LocalResult,
4        prelude::*,
5    },
6    async_proto_derive::impl_protocol_for,
7    crate::{
8        Protocol,
9        ReadErrorKind,
10    },
11};
12
13#[derive(Protocol)]
14#[async_proto(internal)]
15struct NaiveDateProxy {
16    num_days_from_ce: i32,
17}
18
19impl TryFrom<NaiveDateProxy> for NaiveDate {
20    type Error = ReadErrorKind;
21
22    fn try_from(NaiveDateProxy { num_days_from_ce }: NaiveDateProxy) -> Result<Self, ReadErrorKind> {
23        Self::from_num_days_from_ce_opt(num_days_from_ce).ok_or_else(|| ReadErrorKind::Custom(format!("out-of-range date")))
24    }
25}
26
27impl<'a> From<&'a NaiveDate> for NaiveDateProxy {
28    fn from(date: &NaiveDate) -> Self {
29        Self { num_days_from_ce: date.num_days_from_ce() }
30    }
31}
32
33#[derive(Protocol)]
34#[async_proto(internal)]
35struct FixedOffsetProxy {
36    east: i32,
37}
38
39impl TryFrom<FixedOffsetProxy> for FixedOffset {
40    type Error = ReadErrorKind;
41
42    fn try_from(FixedOffsetProxy { east }: FixedOffsetProxy) -> Result<Self, ReadErrorKind> {
43        Self::east_opt(east).ok_or_else(|| ReadErrorKind::Custom(format!("FixedOffset::east out of bounds")))
44    }
45}
46
47impl<'a> From<&'a FixedOffset> for FixedOffsetProxy {
48    fn from(offset: &FixedOffset) -> Self {
49        Self { east: offset.local_minus_utc() }
50    }
51}
52
53#[derive(Protocol)]
54#[async_proto(internal)]
55struct DateTimeProxy<Tz: TimeZone> {
56    timezone: Tz,
57    timestamp: i64,
58    timestamp_subsec_nanos: u32,
59}
60
61impl<Tz: TimeZone> TryFrom<DateTimeProxy<Tz>> for DateTime<Tz> {
62    type Error = ReadErrorKind;
63
64    fn try_from(DateTimeProxy { timezone, timestamp, timestamp_subsec_nanos }: DateTimeProxy<Tz>) -> Result<Self, ReadErrorKind> {
65        match timezone.timestamp_opt(timestamp, timestamp_subsec_nanos) {
66            LocalResult::Single(dt) => Ok(dt),
67            LocalResult::None => Err(ReadErrorKind::Custom(format!("read a nonexistent timestamp"))),
68            LocalResult::Ambiguous(dt1, dt2) => Err(ReadErrorKind::Custom(format!("read an ambiguous timestamp that could refer to {:?} or {:?}", dt1, dt2))),
69        }
70    }
71}
72
73impl<'a, Tz: TimeZone> From<&'a DateTime<Tz>> for DateTimeProxy<Tz> {
74    fn from(date: &DateTime<Tz>) -> Self {
75        Self {
76            timezone: date.timezone(),
77            timestamp: date.timestamp(),
78            timestamp_subsec_nanos: date.timestamp_subsec_nanos(),
79        }
80    }
81}
82
83impl_protocol_for! {
84    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "chrono")))))]
85    struct Utc;
86
87    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "chrono")))))]
88    #[async_proto(via = NaiveDateProxy)]
89    type NaiveDate;
90
91    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "chrono")))))]
92    #[async_proto(via = FixedOffsetProxy)]
93    type FixedOffset;
94
95    #[async_proto(attr(cfg_attr(docsrs, doc(cfg(feature = "chrono")))))]
96    #[async_proto(via = DateTimeProxy<Tz>, where(Tz: Protocol + TimeZone + Send + Sync + 'static, Tz::Offset: Sync))]
97    type DateTime<Tz: TimeZone>;
98}