diesel/pg/types/date_and_time/
mod.rs

1use std::ops::Add;
2
3use crate::deserialize::{self, FromSql, FromSqlRow};
4use crate::expression::AsExpression;
5use crate::pg::{Pg, PgValue};
6use crate::serialize::{self, IsNull, Output, ToSql};
7use crate::sql_types::{self, Date, Interval, Time, Timestamp, Timestamptz};
8
9#[cfg(feature = "chrono")]
10mod chrono;
11#[cfg(feature = "quickcheck")]
12mod quickcheck_impls;
13mod std_time;
14#[cfg(feature = "time")]
15mod time;
16
17#[cfg(feature = "postgres_backend")]
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, AsExpression, FromSqlRow)]
19#[diesel(sql_type = Timestamp)]
20#[diesel(sql_type = Timestamptz)]
21/// Timestamps are represented in Postgres as a 64 bit signed integer representing the number of
22/// microseconds since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate
23/// the integer's meaning.
24pub struct PgTimestamp(pub i64);
25
26#[cfg(feature = "postgres_backend")]
27#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, AsExpression, FromSqlRow)]
28#[diesel(sql_type = Date)]
29/// Dates are represented in Postgres as a 32 bit signed integer representing the number of julian
30/// days since January 1st 2000. This struct is a dumb wrapper type, meant only to indicate the
31/// integer's meaning.
32pub struct PgDate(pub i32);
33
34/// Time is represented in Postgres as a 64 bit signed integer representing the number of
35/// microseconds since midnight. This struct is a dumb wrapper type, meant only to indicate the
36/// integer's meaning.
37#[cfg(feature = "postgres_backend")]
38#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, AsExpression, FromSqlRow)]
39#[diesel(sql_type = Time)]
40pub struct PgTime(pub i64);
41
42/// Intervals in Postgres are separated into 3 parts. A 64 bit integer representing time in
43/// microseconds, a 32 bit integer representing number of days, and a 32 bit integer
44/// representing number of months. This struct is a dumb wrapper type, meant only to indicate the
45/// meaning of these parts.
46#[cfg(feature = "postgres_backend")]
47#[derive(Debug, Clone, Copy, PartialEq, Eq, AsExpression, FromSqlRow)]
48#[diesel(sql_type = Interval)]
49pub struct PgInterval {
50    /// The number of whole microseconds
51    pub microseconds: i64,
52    /// The number of whole days
53    pub days: i32,
54    /// The number of whole months
55    pub months: i32,
56}
57
58impl PgInterval {
59    /// Constructs a new `PgInterval`
60    ///
61    /// No conversion occurs on the arguments. It is valid to provide a number
62    /// of microseconds greater than the longest possible day, or a number of
63    /// days greater than the longest possible month, as it is impossible to say
64    /// how many months are in "40 days" without knowing a precise date.
65    pub fn new(microseconds: i64, days: i32, months: i32) -> Self {
66        PgInterval {
67            microseconds,
68            days,
69            months,
70        }
71    }
72
73    /// Equivalent to `new(microseconds, 0, 0)`
74    pub fn from_microseconds(microseconds: i64) -> Self {
75        Self::new(microseconds, 0, 0)
76    }
77
78    /// Equivalent to `new(0, days, 0)`
79    pub fn from_days(days: i32) -> Self {
80        Self::new(0, days, 0)
81    }
82
83    /// Equivalent to `new(0, 0, months)`
84    pub fn from_months(months: i32) -> Self {
85        Self::new(0, 0, months)
86    }
87}
88
89#[cfg(feature = "postgres_backend")]
90impl ToSql<sql_types::Timestamp, Pg> for PgTimestamp {
91    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
92        ToSql::<sql_types::BigInt, Pg>::to_sql(&self.0, out)
93    }
94}
95
96#[cfg(feature = "postgres_backend")]
97impl FromSql<sql_types::Timestamp, Pg> for PgTimestamp {
98    fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
99        FromSql::<sql_types::BigInt, Pg>::from_sql(bytes).map(PgTimestamp)
100    }
101}
102
103#[cfg(feature = "postgres_backend")]
104impl ToSql<sql_types::Timestamptz, Pg> for PgTimestamp {
105    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
106        ToSql::<sql_types::Timestamp, Pg>::to_sql(self, out)
107    }
108}
109
110#[cfg(feature = "postgres_backend")]
111impl FromSql<sql_types::Timestamptz, Pg> for PgTimestamp {
112    fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
113        FromSql::<sql_types::Timestamp, Pg>::from_sql(bytes)
114    }
115}
116
117#[cfg(feature = "postgres_backend")]
118impl ToSql<sql_types::Date, Pg> for PgDate {
119    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
120        ToSql::<sql_types::Integer, Pg>::to_sql(&self.0, out)
121    }
122}
123
124#[cfg(feature = "postgres_backend")]
125impl FromSql<sql_types::Date, Pg> for PgDate {
126    fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
127        FromSql::<sql_types::Integer, Pg>::from_sql(bytes).map(PgDate)
128    }
129}
130
131#[cfg(feature = "postgres_backend")]
132impl ToSql<sql_types::Time, Pg> for PgTime {
133    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
134        ToSql::<sql_types::BigInt, Pg>::to_sql(&self.0, out)
135    }
136}
137
138#[cfg(feature = "postgres_backend")]
139impl FromSql<sql_types::Time, Pg> for PgTime {
140    fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
141        FromSql::<sql_types::BigInt, Pg>::from_sql(bytes).map(PgTime)
142    }
143}
144
145#[cfg(feature = "postgres_backend")]
146impl ToSql<sql_types::Interval, Pg> for PgInterval {
147    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
148        ToSql::<sql_types::BigInt, Pg>::to_sql(&self.microseconds, out)?;
149        ToSql::<sql_types::Integer, Pg>::to_sql(&self.days, out)?;
150        ToSql::<sql_types::Integer, Pg>::to_sql(&self.months, out)?;
151        Ok(IsNull::No)
152    }
153}
154
155#[cfg(feature = "postgres_backend")]
156impl FromSql<sql_types::Interval, Pg> for PgInterval {
157    fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
158        Ok(PgInterval {
159            microseconds: FromSql::<sql_types::BigInt, Pg>::from_sql(value.subslice(0..8))?,
160            days: FromSql::<sql_types::Integer, Pg>::from_sql(value.subslice(8..12))?,
161            months: FromSql::<sql_types::Integer, Pg>::from_sql(value.subslice(12..16))?,
162        })
163    }
164}
165
166impl Add<PgInterval> for PgInterval {
167    type Output = PgInterval;
168
169    fn add(self, other: PgInterval) -> Self::Output {
170        PgInterval {
171            microseconds: self.microseconds + other.microseconds,
172            days: self.days + other.days,
173            months: self.months + other.months,
174        }
175    }
176}