rbdc_pg/types/
date.rs

1use crate::arguments::PgArgumentBuffer;
2use crate::types::decode::Decode;
3use crate::types::encode::{Encode, IsNull};
4use crate::value::{PgValue, PgValueFormat};
5use rbdc::date::Date;
6use rbdc::Error;
7use std::str::FromStr;
8use std::time::Duration;
9
10impl Decode for fastdate::Date {
11    fn decode(value: PgValue) -> Result<Self, Error> {
12        Ok(match value.format() {
13            PgValueFormat::Binary => {
14                // DATE is encoded as the days since epoch
15                let days: i32 = Decode::decode(value)?;
16                let dt = fastdate::DateTime::from((
17                    fastdate::Date {
18                        day: 1,
19                        mon: 1,
20                        year: 2000,
21                    },
22                    fastdate::Time {
23                        nano: 0,
24                        sec: 0,
25                        minute: 0,
26                        hour: 0,
27                    },
28                ));
29                let dt = {
30                    if days < 0 {
31                        dt - Duration::from_secs((-days * 24 * 3600) as u64)
32                    } else {
33                        dt + Duration::from_secs((days * 24 * 3600) as u64)
34                    }
35                };
36                fastdate::Date::from(dt)
37            }
38
39            PgValueFormat::Text => {
40                let dt = fastdate::DateTime::from_str(&format!("{}T00:00:00Z", value.as_str()?))
41                    .map_err(|e| Error::from(e.to_string()))?;
42                fastdate::Date::from(dt)
43            }
44        })
45    }
46}
47
48impl Encode for fastdate::Date {
49    fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
50        // DATE is encoded as the days since epoch
51
52        let days = (fastdate::DateTime::from((
53            fastdate::Date {
54                day: self.day,
55                mon: self.mon,
56                year: self.year,
57            },
58            fastdate::Time {
59                nano: 0,
60                sec: 0,
61                minute: 0,
62                hour: 0,
63            },
64        ))
65        .unix_timestamp_millis()
66            - fastdate::DateTime::from((
67                fastdate::Date {
68                    day: 1,
69                    mon: 1,
70                    year: 2000,
71                },
72                fastdate::Time {
73                    nano: 0,
74                    sec: 0,
75                    minute: 0,
76                    hour: 0,
77                },
78            ))
79            .unix_timestamp_millis())
80            / (86400 * 1000) as i64;
81        (days as i32).encode(buf)
82    }
83}
84
85impl Decode for Date {
86    fn decode(value: PgValue) -> Result<Self, Error> {
87        Ok(Self(fastdate::Date::decode(value)?))
88    }
89}
90
91impl Encode for Date {
92    fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
93        self.0.encode(buf)
94    }
95}