rbdc_pg/types/
datetime.rs1use crate::arguments::PgArgumentBuffer;
2use crate::types::decode::Decode;
3use crate::types::encode::{Encode, IsNull};
4use crate::value::{PgValue, PgValueFormat};
5use byteorder::{BigEndian, ReadBytesExt};
6use rbdc::datetime::DateTime;
7use rbdc::Error;
8use std::io::Cursor;
9use std::str::FromStr;
10use std::time::Duration;
11
12impl Encode for DateTime {
14 fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
15 let mut millis = self.unix_timestamp_millis();
16 if let Some(tz_sec) = buf.timezone_sec {
18 millis = millis + Duration::from_secs(tz_sec as u64).as_millis() as i64;
19 }
20 let epoch = fastdate::DateTime::from(fastdate::Date {
21 day: 1,
22 mon: 1,
23 year: 2000,
24 });
25 let dt = fastdate::DateTime::from_timestamp_millis(millis);
26 let micros;
27 if dt >= epoch {
28 micros = (dt - epoch).as_micros() as i64;
29 } else {
30 micros = (epoch - dt).as_micros() as i64 * -1;
31 }
32 micros.encode(buf)
33 }
34}
35
36impl Decode for DateTime {
37 fn decode(value: PgValue) -> Result<Self, Error> {
38 Ok(match value.format() {
39 PgValueFormat::Binary => {
40 let mut buf = Cursor::new(value.as_bytes()?);
41 let us = buf.read_i64::<BigEndian>()?;
42 let epoch = fastdate::DateTime::from(fastdate::Date {
43 day: 1,
44 mon: 1,
45 year: 2000,
46 });
47 let v = {
48 if us < 0 {
49 epoch - std::time::Duration::from_micros(-us as u64)
50 } else {
51 epoch + std::time::Duration::from_micros(us as u64)
52 }
53 };
54 let mut dt = DateTime(fastdate::DateTime::from_timestamp_millis(
55 v.unix_timestamp_millis(),
56 ));
57 if let Some(tz_sec) = value.timezone_sec {
59 dt = dt.set_offset(tz_sec);
60 }
61 dt
62 }
63 PgValueFormat::Text => {
64 let s = value.as_str()?;
65 let date =
66 fastdate::DateTime::from_str(s).map_err(|e| Error::from(e.to_string()))?;
67 DateTime(date)
68 }
69 })
70 }
71}