How do I store a timezone aware date using Diesel (Rust)?

Viewed 286

I would like to store timezone-aware dates in Postgres, but I am struggling figure out how to do so. I have included the chrono feature for diesel in my cargo.toml.

Here is the relevant portion of my schema.rs:

table! {
    budgets (id) {
        id -> Uuid,
        is_shared -> Bool,
        is_private -> Bool,
        is_deleted -> Bool,
        name -> Varchar,
        description -> Nullable<Text>,
        start_date -> Timestamptz,
        end_date -> Timestamptz,
        latest_entry_time -> Timestamp,
        modified_timestamp -> Timestamp,
        created_timestamp -> Timestamp,
    }
}

And my model:

#[derive(Debug, Serialize, Deserialize, Associations, Identifiable, Queryable, QueryableByName)]
#[table_name = "budgets"]
pub struct Budget {
    pub id: uuid::Uuid,
    pub is_shared: bool,
    pub is_private: bool,
    pub is_deleted: bool,

    pub name: String,
    pub description: Option<String>,

    pub start_date: DateTime<FixedOffset>,
    pub end_date: DateTime<FixedOffset>,
    pub latest_entry_time: NaiveDateTime,

    pub modified_timestamp: NaiveDateTime,
    pub created_timestamp: NaiveDateTime,
}

#[derive(Debug, Insertable)]
#[table_name = "budgets"]
pub struct NewBudget<'a> {
    pub id: uuid::Uuid,
    pub is_shared: bool,
    pub is_private: bool,
    pub is_deleted: bool,

    pub name: &'a str,
    pub description: Option<&'a str>,

    pub start_date: DateTime<FixedOffset>,
    pub end_date: DateTime<FixedOffset>,
    pub latest_entry_time: NaiveDateTime,

    pub modified_timestamp: NaiveDateTime,
    pub created_timestamp: NaiveDateTime,
}

When I try to build, I get this error when I try to use the model:

error[E0277]: the trait bound `chrono::DateTime<chrono::FixedOffset>: FromSql<diesel::sql_types::Timestamptz, Pg>` is not satisfied
    --> src/utils/db/budget.rs:20:42
     |
20   |     let budget = budgets.find(budget_id).first::<Budget>(db_connection)?;
     |                                          ^^^^^ the trait `FromSql<diesel::sql_types::Timestamptz, Pg>` is not implemented for `chrono::DateTime<chrono::FixedOffset>`
     |
     = help: the following implementations were found:
               <chrono::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 `chrono::DateTime<chrono::FixedOffset>`
     = note: 2 redundant requirements hidden
     = note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Uuid, diesel::sql_types::Bool, diesel::sql_types::Bool, diesel::sql_types::Bool, diesel::sql_types::Text, diesel::sql_types::Nullable<diesel::sql_types::Text>, diesel::sql_types::Timestamptz, diesel::sql_types::Timestamptz, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), Pg>` for `Budget`
     = note: required because of the requirements on the impl of `LoadQuery<_, Budget>` for `diesel::query_builder::SelectStatement<budgets::table, query_builder::select_clause::DefaultSelectClause, query_builder::distinct_clause::NoDistinctClause, query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<budgets::columns::id, diesel::expression::bound::Bound<diesel::sql_types::Uuid, &uuid::Uuid>>>, query_builder::order_clause::NoOrderClause, query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<BigInt, i64>>>`
note: required by a bound in `first`
    --> /Users/tanner/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.8/src/query_dsl/mod.rs:1343:22
     |
1343 |         Limit<Self>: LoadQuery<Conn, U>,
     |                      ^^^^^^^^^^^^^^^^^^ required by this bound in `first`

Here is the function that the error refers to:

pub fn get_budget_by_id(
    db_connection: &DbConnection,
    budget_id: &Uuid,
) -> Result<OutputBudget, diesel::result::Error> {
    let budget = budgets.find(budget_id).first::<Budget>(db_connection)?;

    let loaded_categories = Category::belonging_to(&budget).load::<Category>(db_connection)?;

    let output_budget = OutputBudget {
        id: budget.id,
        is_shared: budget.is_shared,
        is_private: budget.is_private,
        is_deleted: budget.is_deleted,
        name: budget.name,
        description: budget.description,
        categories: loaded_categories,
        start_date: budget.start_date,
        end_date: budget.end_date,
        latest_entry_time: budget.latest_entry_time,
        modified_timestamp: budget.modified_timestamp,
        created_timestamp: budget.created_timestamp,
    };

    Ok(output_budget)
}

I would like to be able to store timestamps from multiple timezones. Can I only use chrono::DateTime<Utc> or am I missing something?

0 Answers
Related