1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use chrono_04::{DateTime, Duration, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, Utc}; use postgres_protocol::types; use std::error::Error; use crate::types::{FromSql, IsNull, ToSql, Type}; fn base() -> NaiveDateTime { NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0) } impl<'a> FromSql<'a> for NaiveDateTime { fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDateTime, Box<dyn Error + Sync + Send>> { let t = types::timestamp_from_sql(raw)?; Ok(base() + Duration::microseconds(t)) } accepts!(TIMESTAMP); } impl ToSql for NaiveDateTime { fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> { let time = match self.signed_duration_since(base()).num_microseconds() { Some(time) => time, None => return Err("value too large to transmit".into()), }; types::timestamp_to_sql(time, w); Ok(IsNull::No) } accepts!(TIMESTAMP); to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime<Utc> { fn from_sql(type_: &Type, raw: &[u8]) -> Result<DateTime<Utc>, Box<dyn Error + Sync + Send>> { let naive = NaiveDateTime::from_sql(type_, raw)?; Ok(DateTime::from_utc(naive, Utc)) } accepts!(TIMESTAMPTZ); } impl ToSql for DateTime<Utc> { fn to_sql( &self, type_: &Type, w: &mut Vec<u8>, ) -> Result<IsNull, Box<dyn Error + Sync + Send>> { self.naive_utc().to_sql(type_, w) } accepts!(TIMESTAMPTZ); to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime<Local> { fn from_sql(type_: &Type, raw: &[u8]) -> Result<DateTime<Local>, Box<dyn Error + Sync + Send>> { let utc = DateTime::<Utc>::from_sql(type_, raw)?; Ok(utc.with_timezone(&Local)) } accepts!(TIMESTAMPTZ); } impl ToSql for DateTime<Local> { fn to_sql( &self, type_: &Type, w: &mut Vec<u8>, ) -> Result<IsNull, Box<dyn Error + Sync + Send>> { self.with_timezone(&Utc).to_sql(type_, w) } accepts!(TIMESTAMPTZ); to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime<FixedOffset> { fn from_sql( type_: &Type, raw: &[u8], ) -> Result<DateTime<FixedOffset>, Box<dyn Error + Sync + Send>> { let utc = DateTime::<Utc>::from_sql(type_, raw)?; Ok(utc.with_timezone(&FixedOffset::east(0))) } accepts!(TIMESTAMPTZ); } impl ToSql for DateTime<FixedOffset> { fn to_sql( &self, type_: &Type, w: &mut Vec<u8>, ) -> Result<IsNull, Box<dyn Error + Sync + Send>> { self.with_timezone(&Utc).to_sql(type_, w) } accepts!(TIMESTAMPTZ); to_sql_checked!(); } impl<'a> FromSql<'a> for NaiveDate { fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveDate, Box<dyn Error + Sync + Send>> { let jd = types::date_from_sql(raw)?; Ok(base().date() + Duration::days(i64::from(jd))) } accepts!(DATE); } impl ToSql for NaiveDate { fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> { let jd = self.signed_duration_since(base().date()).num_days(); if jd > i64::from(i32::max_value()) || jd < i64::from(i32::min_value()) { return Err("value too large to transmit".into()); } types::date_to_sql(jd as i32, w); Ok(IsNull::No) } accepts!(DATE); to_sql_checked!(); } impl<'a> FromSql<'a> for NaiveTime { fn from_sql(_: &Type, raw: &[u8]) -> Result<NaiveTime, Box<dyn Error + Sync + Send>> { let usec = types::time_from_sql(raw)?; Ok(NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(usec)) } accepts!(TIME); } impl ToSql for NaiveTime { fn to_sql(&self, _: &Type, w: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> { let delta = self.signed_duration_since(NaiveTime::from_hms(0, 0, 0)); let time = match delta.num_microseconds() { Some(time) => time, None => return Err("value too large to transmit".into()), }; types::time_to_sql(time, w); Ok(IsNull::No) } accepts!(TIME); to_sql_checked!(); }