我正在尝试使用 postgres-rs 显示本地时间,其中 time-rs 0.3 而不是 chrono-rs 0.4。但将时区设置为 Europe/Amsterdam 时,我得到的只是 UTC 时间戳,没有时区信息来纠正它。
从 psql
show timezone; select now();
读取 Europe/Amsterdam
和 2024-10-01 10:38:36.63829+02
。
但是当我在 Rust 中尝试同样的事情时:
// mut conn: PooledConnection<PostgresConnectionManager<MakeTlsConnector>>
let mut tz: Option<String> = None;
if let Ok(r) = conn.query_one("show timezone", &[]) { tz = r.get(0); }
println!("timezone: {:?}", tz);
let mut now: Option<OffsetDateTime> = None;
if let Ok(r) = conn.query_one("select now()", &[]) { now = r.get(0); }
println!("now: {:?}", now);
我得到:
timezone: Some("Europe/Amsterdam")
now: Some(2024-10-01 8:41:49.767418 +00:00:00)
如果没有 OffsetDateTime.offset() 的适当值,我如何正确显示当地时间?
Postgres 将
TIMESTAMPTZ
存储为 UTC,就像 TIMESTAMP
一样。唯一的区别是第一种类型表示任何值都应该在本地解释。因此,在存储和显示之前,值会被转换为UTC/从UTC。
根据文档,可以预期类型为
TIMEZONETZ
的值将在数据库连接上设置的区域设置中返回:
所有时区感知的日期和时间均以 UTC 内部存储。他们 转换为 TimeZone 指定区域的本地时间 显示给客户端之前的配置参数。
您可能会将 “在显示给” 之前解释为 “在发送给” 之前,但实际上它归结为 “在由 客户显示之前”。
来自此线程:
诸如 psql 或 pgAdmin 之类的客户端或任何通过以下方式进行通信的应用程序 libpq(就像带有 pg gem 的 Ruby)提供了偏移量 当前时区或根据给定时区 [..]实际上,转换不是在服务器端进行,而是通过
libpq
在客户端进行。 因为您没有在 Rust 中使用任何与
libpq
的直接绑定,所以 TIMESTAMPTZ
值仍然采用 UTC。最简单的解决方案是
使用 chrono 0.4, 因为在 chrono-rs 之上有 chrono-tz-rs,它可以使用 IANA 数据库从 UTC 进行转换:
// row: &postgres::Row
Option<stdDateTime<Local>> = row.get(index);