-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support jiff as a date time lib backend #3487
Comments
I have no strong opinions on See also this comment: BurntSushi/jiff#50 (comment) |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
For reference, here is a wrapper that can be used to bridge jiff's Timestamp to Postgres' TIMESTAMPTZ: use std::str::FromStr;
use jiff::SignedDuration;
use serde::Deserialize;
use serde::Serialize;
use sqlx::encode::IsNull;
use sqlx::error::BoxDynError;
use sqlx::postgres::types::Oid;
use sqlx::postgres::PgArgumentBuffer;
use sqlx::postgres::PgHasArrayType;
use sqlx::postgres::PgTypeInfo;
use sqlx::postgres::PgValueFormat;
use sqlx::Database;
use sqlx::Decode;
use sqlx::Encode;
use sqlx::Postgres;
use sqlx::Type;
/// A module for Jiff support of SQLx.
// TODO(tisonkun): either switch to the upstream [1] or spawn a dedicate open-source crate.
// [1] https://github.com/launchbadge/sqlx/pull/3511
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Timestamp(pub jiff::Timestamp);
impl Type<Postgres> for Timestamp {
fn type_info() -> PgTypeInfo {
// 1184 => PgType::Timestamptz
PgTypeInfo::with_oid(Oid(1184))
}
}
impl PgHasArrayType for Timestamp {
fn array_type_info() -> PgTypeInfo {
// 1185 => PgType::TimestamptzArray
PgTypeInfo::with_oid(Oid(1185))
}
}
impl Encode<'_, Postgres> for Timestamp {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
// TIMESTAMP is encoded as the microseconds since the epoch
let micros = self
.0
.duration_since(postgres_epoch_timestamp())
.as_micros();
let micros = i64::try_from(micros)
.map_err(|_| format!("Timestamp {} out of range for Postgres: {micros}", self.0))?;
Encode::<Postgres>::encode(micros, buf)
}
fn size_hint(&self) -> usize {
size_of::<i64>()
}
}
impl<'r> Decode<'r, Postgres> for Timestamp {
fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
Ok(match value.format() {
PgValueFormat::Binary => {
// TIMESTAMP is encoded as the microseconds since the epoch
let us = Decode::<Postgres>::decode(value)?;
let ts = postgres_epoch_timestamp().checked_add(SignedDuration::from_micros(us))?;
Timestamp(ts)
}
PgValueFormat::Text => {
let s = value.as_str()?;
let ts = jiff::Timestamp::from_str(s)?;
Timestamp(ts)
}
})
}
}
fn postgres_epoch_timestamp() -> jiff::Timestamp {
jiff::Timestamp::from_str("2000-01-01T00:00:00Z")
.expect("2000-01-01T00:00:00Z is a valid timestamp")
} For full integration if we are back to here and continue, sfackler/rust-postgres#1164 is a good reference for data type mapping and edge cases (error handling). |
As in https://docs.rs/sqlx/0.8.2/sqlx/postgres/types/index.html for
chrono
andtime
, being integrated withjiff
.Since the abstractions are similar, it should be viable.
cc @BurntSushi
I may take a closer look later but I can't commit it :P
The text was updated successfully, but these errors were encountered: