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

如何配置pg库将PostgreSQL无时区时间戳读取为UTC时间戳

问题描述
  • 本地时区:UTC/GMT +3小时
  • 数据库表结构(PostgreSQL):
CREATE TABLE public.order_invoices (
    created_at timestamp NOT NULL,
    updated_at timestamp NOT NULL,
    order_id uuid NOT NULL,
    document_id varchar(100) NULL,
    status varchar(20) NOT NULL,
    CONSTRAINT order_invoices_pkey PRIMARY KEY (order_id)
);
  • 写入数据的代码:
markInvoiceWaitingForApf(order: Order): Promise<void> {
  return this.sql.executeInTransaction(async tx => {
    await tx.executeStatement(
      `INSERT INTO order_invoices(order_id, status, created_at, updated_at) 
       VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
       ON CONFLICT (order_id) DO
       UPDATE SET updated_at = CURRENT_TIMESTAMP, status = $2
       WHERE order_invoices.status = 'WAITING_FOR_APF'`,
      [order.id, OrderInvoiceStatus.WAITING_FOR_APF, parseISO(order.orderDate).toISOString()])
  })
}

底层通过pg.ClientBase.query(sql, params)执行,客户端由const client = await pg.Pool.connect()创建。

  • 现象:写入时的时间为"2024-07-09T12:32:30.214Z",读取后得到"2024-07-09T09:32:30.227Z",pg库默认将PostgreSQL的无时区时间戳解析为本地时间戳,导致时区偏移。
解决方案

pg库允许通过自定义类型解析器修改无时区时间戳(timestamp类型,OID为1114)的解析行为,以下两种方式可解决问题:

方式1:解析为UTC时间戳

修改类型解析器,将数据库返回的时间字符串当作UTC时间处理,生成的Date对象调用toISOString()会得到正确的UTC时间:

const { types } = require('pg');

// 配置PostgreSQL timestamp类型(无时区)的解析器
types.setTypeParser(1114, (value) => {
  // 在原始时间字符串后添加Z,标记为UTC时间
  return new Date(`${value}Z`);
});

方式2:读取为原始字符串(Naive时间戳)

如果不需要转换为Date对象,直接获取数据库中存储的原始时间字符串:

const { types } = require('pg');

types.setTypeParser(1114, (value) => {
  // 直接返回数据库中的原始时间字符串,如'2024-07-09 12:32:30.214'
  return value;
});

补充说明

写入时使用toISOString()生成的是UTC时间字符串,PostgreSQL的timestamp字段会丢弃时区信息,仅保留时间部分。默认解析逻辑会将该时间视为本地时间(UTC+3),转换为UTC时自动减去3小时,导致结果偏移。通过上述配置可覆盖默认解析行为,得到预期的时间值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:33:13