为何JSONB输出的日期格式与JavaScript不一致?
为什么JavaScript的.toISOString()/.toJSON()和PostgreSQL的to_jsonb输出的日期格式不一样?
这俩差异的核心原因其实很简单——两者对日期时区的处理逻辑完全不同,咱们结合你的例子一步步拆解:
1. JavaScript这边的逻辑
在JS里,(new Date()).toISOString() 和 .toJSON() 有个统一的规则:不管你的本地系统时区是啥,它们都会把日期时间转换成UTC时区的ISO 8601格式,结尾的Z就是UTC的专属标记(代表Zero时区偏移)。
就像你例子里的2018-01-30T12:04:13.153Z,这就是标准的UTC时间,是全球统一的时间点。
2. PostgreSQL的to_jsonb是怎么处理的
PostgreSQL里的timestamp with time zone(简称timestamptz),本质上存储的是UTC时间,但在输出(包括用to_jsonb转成JSON格式)的时候,会自动根据当前会话的时区设置转换成对应时区的本地时间,并且显示具体的时区偏移量(而不是用Z)。
看你的例子:
你输入的'2018-01-30T12:04:13.153Z'::timestamptz本身是UTC时间,但你的PostgreSQL会话时区应该是UTC-6(比如美国中部时区),所以to_jsonb会把UTC的12:04转换成会话时区的06:04,然后输出带-06:00偏移的格式,也就是你看到的"2018-01-30T06:04:13.153-06:00"。
如果你想让PostgreSQL输出和JS完全一致的UTC格式,有两个简单办法:
- 临时把会话时区改成UTC:
SET TIME ZONE 'UTC';,之后再执行to_jsonb就会输出带Z的UTC格式。 - 直接用
to_char手动格式化后转JSONB:to_jsonb(to_char('2018-01-30T12:04:13.153Z'::timestamptz, 'YYYY-MM-DD"T"HH24:MI:SS.US"Z"'));
一句话总结
- JS的这两个方法是强制输出UTC时间,用
Z标记; - PostgreSQL的
to_jsonb是跟着会话时区走,输出对应时区的时间+偏移量。
内容的提问来源于stack exchange,提问作者Vincent Vost
相关产品推荐
相关产品推荐

