如何使用tokio_postgres插入timestamp类型数据?
解决Rust u32时间戳插入PostgreSQL timestamp字段的类型不匹配问题
问题原因
PostgreSQL的timestamp without time zone字段需要接收时间类型值,但tokio-postgres的ToSql trait默认并未实现u32到PostgreSQL Timestamp的直接转换——u32会被映射为PostgreSQL的integer类型,因此触发类型不匹配错误。
解决方案
方案1:使用chrono库转换为时间类型(推荐)
借助chrono库将u32秒级时间戳转换为NaiveDateTime(对应timestamp without time zone),该类型已实现ToSql trait,可直接作为参数传入。
- 添加依赖到
Cargo.toml:
chrono = { version = "0.4", features = ["postgres"] }
- 修改代码:
use tokio_postgres::NoTls; use chrono::NaiveDateTime; let mut params: Vec<&(dyn ToSql + Sync)> = vec![]; let mut query = String::from("INSERT INTO tokens (created) VALUES ($1)"); let timestamp: u32 = 123; // 将u32秒级时间戳转换为NaiveDateTime let naive_dt = NaiveDateTime::from_timestamp_opt(timestamp as i64, 0) .expect("Invalid timestamp"); // 或用?处理错误,根据业务场景调整 params.push(&naive_dt as &(dyn ToSql + Sync)); let client = DB_POOL.get().await?; client .execute(&query, ¶ms) .await?;
方案2:在SQL中直接转换(无需额外依赖)
利用PostgreSQL内置的to_timestamp()函数,将传入的u32数值直接转换为timestamp类型,无需修改Rust端的类型转换逻辑。
修改后的代码:
use tokio_postgres::NoTls; let mut params: Vec<&(dyn ToSql + Sync)> = vec![]; // 修改SQL,使用to_timestamp转换参数 let mut query = String::from("INSERT INTO tokens (created) VALUES (to_timestamp($1))"); let timestamp: u32 = 123; params.push(×tamp as &(dyn ToSql + Sync)); let client = DB_POOL.get().await?; client .execute(&query, ¶ms) .await?;
补充说明
- 若你的u32时间戳是毫秒级而非秒级,方案1中需调整转换逻辑:
NaiveDateTime::from_timestamp_millis(timestamp as i64);方案2中需用to_timestamp($1 / 1000.0)进行转换。 - 方案1的优势是在Rust端完成类型校验,避免数据库层的转换开销;方案2更轻量,适合快速适配现有代码。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

