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 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 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}