sqlx_core_oldapi/postgres/types/time/
datetime.rs1use crate::decode::Decode;
2use crate::encode::{Encode, IsNull};
3use crate::error::BoxDynError;
4use crate::postgres::types::time::PG_EPOCH;
5use crate::postgres::{
6 PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueFormat, PgValueRef, Postgres,
7};
8use crate::types::Type;
9use std::borrow::Cow;
10use std::mem;
11use time::macros::format_description;
12use time::macros::offset;
13use time::{Duration, OffsetDateTime, PrimitiveDateTime};
14
15impl Type<Postgres> for PrimitiveDateTime {
16 fn type_info() -> PgTypeInfo {
17 PgTypeInfo::TIMESTAMP
18 }
19}
20
21impl Type<Postgres> for OffsetDateTime {
22 fn type_info() -> PgTypeInfo {
23 PgTypeInfo::TIMESTAMPTZ
24 }
25}
26
27impl PgHasArrayType for PrimitiveDateTime {
28 fn array_type_info() -> PgTypeInfo {
29 PgTypeInfo::TIMESTAMP_ARRAY
30 }
31}
32
33impl PgHasArrayType for OffsetDateTime {
34 fn array_type_info() -> PgTypeInfo {
35 PgTypeInfo::TIMESTAMPTZ_ARRAY
36 }
37}
38
39impl Encode<'_, Postgres> for PrimitiveDateTime {
40 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
41 let us =
43 i64::try_from((*self - PG_EPOCH.midnight()).whole_microseconds()).unwrap_or(i64::MAX);
44 Encode::<Postgres>::encode(us, buf)
45 }
46
47 fn size_hint(&self) -> usize {
48 mem::size_of::<i64>()
49 }
50}
51
52impl<'r> Decode<'r, Postgres> for PrimitiveDateTime {
53 fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
54 Ok(match value.format() {
55 PgValueFormat::Binary => {
56 let us = Decode::<Postgres>::decode(value)?;
58 PG_EPOCH.midnight() + Duration::microseconds(us)
59 }
60
61 PgValueFormat::Text => {
62 let s = value.as_str()?;
63
64 let s = if s.contains('.') {
66 Cow::Borrowed(s)
67 } else {
68 Cow::Owned(format!("{}.0", s))
69 };
70
71 if s.contains('+') {
75 PrimitiveDateTime::parse(&s, &format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour]"))?
76 } else {
77 PrimitiveDateTime::parse(
78 &s,
79 &format_description!(
80 "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"
81 ),
82 )?
83 }
84 }
85 })
86 }
87}
88
89impl Encode<'_, Postgres> for OffsetDateTime {
90 fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
91 let utc = self.to_offset(offset!(UTC));
92 let primitive = PrimitiveDateTime::new(utc.date(), utc.time());
93
94 Encode::<Postgres>::encode(primitive, buf)
95 }
96
97 fn size_hint(&self) -> usize {
98 mem::size_of::<i64>()
99 }
100}
101
102impl<'r> Decode<'r, Postgres> for OffsetDateTime {
103 fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
104 Ok(<PrimitiveDateTime as Decode<Postgres>>::decode(value)?.assume_utc())
105 }
106}