我正在使用
sqlx
0.7.3 和 time
0.3.34。
我有这个结构:
#[derive(Debug, sqlx::FromRow)]
pub struct Game {
pub id: String,
pub created_at: time::OffsetDateTime,
pub date_time: time::OffsetDateTime,
pub score: i64,
// and many other fields
}
我可以阅读以下查询:
let query = "SELECT * from games"
let games = query.build_query_as::<Game>().fetch_all(db_connection).await?;
我可以插入查询,例如:
let query = r#"INSERT INTO "games" ("id", ..columns...) VALUES ($1, $2, ...and other values...) RETURNING *"#;
let games = sqlx::query_as::<_, Game>(query)
.bind(value)
.bind(another_value)
.fetch_one(db_connection)
.await?;
一切正常(还有其他更困难的查询)。
现在是问题。
created_at
和date_time
字段以Postgresql的timestamptz
类型保存在数据库中。太棒了。
但是当我检索这些字段时,我需要将它们获取到当前用户的时区。
示例:
如果当前用户查询游戏数据当前位于时区
Europe/Berlin
,Rust 中的后端代码应该在该时区的结构日期时间字段上工作,而不是在 UTC
上工作,这显然是使用 time::OffsetDateTime
与 sqlx 的默认设置。
我知道我可以在 Rust 代码中在后端进行转换(例如将
time::OffsetDateTime
转换为 time::PrimitiveDateTime
或使用 time-tz crate 的方法),但是 我想直接在 Postgresql 中进行转换。
我读到我可以使用
AT TIME ZONE 'Europe/Berlin'
PG 的构造来执行此操作,但是所有查询中的所有日期又如何呢?即使我在 PG 的 CTE 末尾使用类似 RETURNING *
的内容?
我读到我可以在查询之前使用
SET TIME ZONE 'Europe/Berlin'
,并且我尝试过但sqlx的作者回答:
使用二进制协议,始终输出 UTC 时间戳。query_as
所以我现在迷路了。
是否可以让 Postgresql 按查询返回我需要的时区的日期?
你可以使用chrono
DateTime 是时区感知的,必须从 TimeZone 对象构造,该对象定义如何将本地日期转换为 和 从 UTC 日期返回。有3个著名的时区 实施:
- Utc 指定 UTC 时区。这是最有效率的。
使用 chrono::{DateTime, Utc};
pub struct Game {
pub id: String,
pub created_at: time::DateTime<Utc>,,
pub date_time: time::DateTime<Utc>,,
}