Skip to content

Commit

Permalink
Add FromSql/ToSql<Timestamp> to Pg backend for OffsetDateTime
Browse files Browse the repository at this point in the history
  • Loading branch information
jeff-hiner committed Mar 29, 2024
1 parent a5c82df commit d53143c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
39 changes: 38 additions & 1 deletion diesel/src/pg/types/date_and_time/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ use super::{PgDate, PgTime, PgTimestamp};
use crate::deserialize::{self, FromSql};
use crate::pg::{Pg, PgValue};
use crate::serialize::{self, Output, ToSql};
use crate::sql_types::{Date, Time, Timestamp, Timestamptz};
use crate::sql_types::{Date, Datetime, Time, Timestamp, Timestamptz};

// Postgres timestamps start from January 1st 2000.
const PG_EPOCH: PrimitiveDateTime = datetime!(2000-1-1 0:00:00);

fn to_primitive_datetime(dt: OffsetDateTime) -> PrimitiveDateTime {
let dt = dt.to_offset(UtcOffset::UTC);
PrimitiveDateTime::new(dt.date(), dt.time())
}

#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl FromSql<Timestamp, Pg> for PrimitiveDateTime {
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
Expand Down Expand Up @@ -44,6 +49,38 @@ impl ToSql<Timestamp, Pg> for PrimitiveDateTime {
}
}

// Delegate offset datetimes in terms of UTC primitive datetimes; this stores everything in the DB as UTC
#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl ToSql<Datetime, Pg> for OffsetDateTime {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
let prim = to_primitive_datetime(*self);
<PrimitiveDateTime as ToSql<Datetime, Pg>>::to_sql(&prim, &mut out.reborrow())
}
}

#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl FromSql<Datetime, Pg> for OffsetDateTime {
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
let prim = <PrimitiveDateTime as FromSql<Datetime, Pg>>::from_sql(bytes)?;
Ok(prim.assume_utc())
}
}

// delegate timestamp column to datetime column for offset datetimes
#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl ToSql<Timestamp, Pg> for OffsetDateTime {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
<OffsetDateTime as ToSql<Datetime, Pg>>::to_sql(self, out)
}
}

#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl FromSql<Timestamp, Pg> for OffsetDateTime {
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
<OffsetDateTime as FromSql<Datetime, Pg>>::from_sql(bytes)
}
}

#[cfg(all(feature = "time", feature = "postgres_backend"))]
impl FromSql<Timestamptz, Pg> for PrimitiveDateTime {
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
Expand Down
4 changes: 2 additions & 2 deletions diesel/src/sql_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,14 @@ pub struct Time;
/// - [`std::time::SystemTime`][SystemTime] (PG only)
/// - [`chrono::NaiveDateTime`][NaiveDateTime] with `feature = "chrono"`
/// - [`time::PrimitiveDateTime`] with `feature = "time"`
/// - [`time::OffsetDateTime`] with `feature = "time"` (MySQL only)
/// - [`time::OffsetDateTime`] with `feature = "time"`
///
/// ### [`FromSql`](crate::deserialize::FromSql) impls
///
/// - [`std::time::SystemTime`][SystemTime] (PG only)
/// - [`chrono::NaiveDateTime`][NaiveDateTime] with `feature = "chrono"`
/// - [`time::PrimitiveDateTime`] with `feature = "time"`
/// - [`time::OffsetDateTime`] with `feature = "time"` (MySQL only)
/// - [`time::OffsetDateTime`] with `feature = "time"`
///
/// [SystemTime]: std::time::SystemTime
#[cfg_attr(
Expand Down

0 comments on commit d53143c

Please sign in to comment.