You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中使用postgres-rs结合time-rs 0.3显示本地时区的TIMESTAMPTZ

问题:postgres-rs + time-rs 0.3 无法正确获取带时区修正的本地时间

问题场景

在Rust中使用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()获取合适偏移值时,如何正确显示本地时间?


解决方案

1. 启用time-rs的时区数据库特性

PostgreSQL的timestamptz类型内部以UTC存储,postgres-rs会直接解析为UTC偏移的OffsetDateTime。要转换为目标时区,需先启用time-rs的tzdb特性来解析时区字符串。

修改Cargo.toml:

time = { version = "0.3", features = ["tzdb", "formatting"] }

2. 手动转换UTC时间到目标时区

先获取数据库时区并解析为time-rs的Tz类型,再将UTC时间转换为对应时区的本地时间:

use time::{OffsetDateTime, Tz};
use postgres::error::Error;

fn get_local_time(conn: &mut PooledConnection<PostgresConnectionManager<MakeTlsConnector>>) -> Result<(), Error> {
    // 获取数据库时区字符串并解析为Tz类型
    let tz_str: String = conn.query_one("show timezone", &[])?.get(0);
    let tz = Tz::try_from(tz_str.as_str()).expect("无效的时区字符串");

    // 获取UTC时间
    let utc_now: OffsetDateTime = conn.query_one("select now()", &[])?.get(0);
    
    // 转换为目标时区的OffsetDateTime(带偏移信息)
    let local_offset_time = utc_now.to_offset(tz);
    // 或转换为本地时间(不带偏移的PrimitiveDateTime)
    let local_primitive_time = utc_now.to_offset(tz).date_time();

    println!("UTC时间: {:?}", utc_now);
    println!("阿姆斯特丹时区时间: {:?}", local_offset_time);
    println!("阿姆斯特丹本地时间: {:?}", local_primitive_time);
    
    // 格式化显示示例
    println!("格式化本地时间: {}", local_offset_time.format("%Y-%m-%d %H:%M:%S %z"));

    Ok(())
}

3. 关键原理说明

PostgreSQL的now()返回的timestamptz在传输给客户端时会转为UTC,postgres-rs的time-rs绑定直接解析为UTC偏移的OffsetDateTime。要得到数据库时区对应的本地时间,必须手动完成UTC到目标时区的偏移转换,这依赖time-rs的时区数据库来解析Europe/Amsterdam这类时区标识。


内容的提问来源于stack exchange,提问作者Code4R7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:54:56