postgresql - DateTime<Utc> 编译但不编译 DateTime<Local> 查询表,该表的列定义为带有时区的时间戳

标签 postgresql datetime rust serde rust-diesel

我有一个 postgresql 表,其中的列定义为 timestamp with time zone 。该表映射到此结构:

#[derive(Serialize, Queryable)]
pub struct Location {
    pub publication_time: DateTime<Utc>,
    pub id: i32,
    pub name: String,
    pub latitude: BigDecimal,
    pub longitude: BigDecimal,
}

架构具有以下定义:

table! {
    locations {
        publication_time -> Timestamptz,
        id -> Integer,
        name -> Text,
        latitude -> Numeric,
        longitude -> Numeric,
    }
}

(部分)Cargo.toml:

serde = "1.0.125"
serde_json = "1.0.64"
serde_derive = "1.0.125"
diesel = { version = "1.4.6", features = ["postgres", "r2d2", "chrono", "numeric"] }
bigdecimal = { version = "0.1.0", features = ["serde"] }
chrono = { version = "0.4.19", features = ["serde"] }

查询数据库的函数:

fn get_all_locations(pool: web::Data<Pool>) -> Result<Vec<Location>, diesel::result::Error> {
    let conn = pool.get().unwrap();
    let items = locations.load::<Location>(&conn)?;
    Ok(items)
}

然后使用 serde_json 将其序列化为 JSON 数组。数据库中的日期时间是 2021-04-08 15:02:02.514+02 。当 DateTime 为 Utc 时,程序可以正常编译,但 DateTime 以 UTC 形式显示,如 2021-04-08T13:02:02.514Z 。我将 Publication_time 更改为 DateTime<Local>保留时区信息,然后 cargo build失败并显示:

error[E0277]: the trait bound `DateTime<Local>: FromSql<diesel::sql_types::Timestamptz, Pg>` is not satisfied
  --> src/controller.rs:21:27
   |
21 |     let items = locations.load::<Location>(&conn)?;
   |                           ^^^^ the trait `FromSql<diesel::sql_types::Timestamptz, Pg>` is not implemented for `DateTime<Local>`
   |
   = help: the following implementations were found:
             <DateTime<Utc> as FromSql<diesel::sql_types::Timestamptz, Pg>>
   = note: required because of the requirements on the impl of `diesel::Queryable<diesel::sql_types::Timestamptz, Pg>` for `DateTime<Local>`
   = note: 2 redundant requirements hidden
   = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Timestamptz, diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Numeric, diesel::sql_types::Numeric), Pg>` for `models::Location`
   = note: required because of the requirements on the impl of `LoadQuery<_, models::Location>` for `locations::table`

我有另一个程序可以插入到该表中,并且该程序有效,唯一的区别是导出(反序列化,可插入)。

#[derive(Deserialize, Insertable)]
pub struct Location {
    pub publication_time: DateTime<Local>,
    pub id: i32,
    pub name: String,
    pub latitude: BigDecimal,
    pub longitude: BigDecimal,
}

最佳答案

映射Timestamptz字段到 DateTime<Local>柴油本身不支持,因为它只提供the corresponding impl对于 DateTime<Utc> 。 您可以使用 #[diesel(deserialize_as = "…")] attribute 来解决此问题在相应的字段上并提供您自己的反序列化包装器:

#[derive(Serialize, Queryable)]
pub struct Location {
    #[diesel(deserialize_as = "MyDateTimeWrapper")]
    pub publication_time: DateTime<Local>,
    pub id: i32,
    pub name: String,
    pub latitude: BigDecimal,
    pub longitude: BigDecimal,
}

pub struct MyDatetimeWrapper(DateTime<Local>);

impl Into<DateTime<Local>> for MyDatetimeWrapper {
    fn into(self) -> DateTime<Local> {
        self.0
    }
}

impl<DB, ST> Queryable<ST, DB> for MyDateTimeWrapper
where
    DB: Backend,
    DateTime<Utc>: Queryable<ST, DB>,
{
    type Row = <DateTime<Utc> as Queryable<ST, DB>>::Row;

    fn build(row: Self::Row) -> Self {
        Self(<DateTime<Utc> as Queryable<ST, DB>>::build(row).with_timezone(&Local))
    }
}

关于postgresql - DateTime<Utc> 编译但不编译 DateTime<Local> 查询表,该表的列定义为带有时区的时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67034813/

相关文章:

ruby-on-rails - Rails/pg group_by 两条记录之间的平均值

sql - 获取 PostgreSQL 中小数点后非零的记录

如果比较两次,例如 : 12:00 and 11:59,Python 日期时间比较不正确

rust - 在 Rust 中使用多个 .c 源文件

database - 逆向工程时如何确定表之间的关系(1:1,1:n,n:m)

java - 如何测试PreparedStatement是否会耗尽内存

PHP strtotime 转换不适用于某些日期时间

datetime - 有没有办法处理java的Google Sheets日期格式 "mmmmm" token ?

generics - 将泛型写入文件

rust - 如何在稳定的 Rust 中分配原始可变指针?