postgresql的to_timestamp函数支持两种用法:一是to_timestamp(text, text)将字符串按指定格式模板(如'yyyy-mm-dd hh24:mi:ss')解析为timestamp without time zone,格式须严格匹配、大小写敏感;二是to_timestamp(double precision)将unix时间戳秒数转换为时间戳。

TO_TIMESTAMP函数的基本用法和格式字符串规则
TO_TIMESTAMP 不是简单按固定分隔符切分字符串的函数,它严格依赖你提供的格式模板(format string)来解析输入。如果模板和实际字符串不完全匹配,会直接报错 ERROR: invalid value for "YYYY": "2024" 这类信息,而不是静默失败或返回 NULL。
格式模板必须用双引号包裹,且大小写敏感:"YYYY-MM-DD HH24:MI:SS" 和 "yyyy-mm-dd hh24:mi:ss" 效果不同;年份必须用大写 YYYY,小时用 HH24 表示 24 小时制。
- 常见错误:把
MM(月)写成mm(分钟),导致月份被误解析为分钟值 - 空格、冒号、短横线等字面字符必须原样出现在模板中,例如
"YYYY/MM/DD HH24:MI:SS"才能匹配'2024/05/12 14:30:45' - 毫秒支持用
MS,但注意 PostgreSQL 的timestamp类型精度默认为微秒,MS只取前三位,多余部分会被截断
处理带时区的字符串(如 '2024-05-12T14:30:45+08')
直接用 TO_TIMESTAMP 解析 ISO 8601 带时区的字符串会失败,因为 TO_TIMESTAMP 本身不识别 +08 或 Z 等时区标识。它只输出 timestamp without time zone 类型。
正确做法是先用 TO_TIMESTAMP 解析出无时区时间,再用 AT TIME ZONE 显式指定时区:
SELECT TO_TIMESTAMP('2024-05-12T14:30:45+08', 'YYYY-MM-DD"T"HH24:MI:SS') AT TIME ZONE 'Asia/Shanghai';
- 模板里用
"T"匹配字面字母 T(必须加双引号包裹) - 不能在模板里写
OF或TZ—— PostgreSQL 的TO_TIMESTAMP不支持自动提取时区偏移 - 如果原始字符串含
Z,需先替换为+00或用REPLACE()处理,再统一转为指定时区
与 TO_DATE、CAST 的关键区别和选型建议
TO_TIMESTAMP 返回的是 timestamp without time zone,而 TO_DATE 只返回日期部分(date 类型),丢失时间信息;CAST('2024-05-12 14:30' AS timestamp) 则只支持标准格式(如 ISO 或 YYYY-MM-DD HH:MI:SS),无法处理自定义分隔符或非标准顺序。
- 需要解析
'12/05/2024 02:30 PM'?必须用TO_TIMESTAMP+"DD/MM/YYYY HH12:MI AM" - 只需要日期且格式规整,
TO_DATE更轻量;但一旦涉及时间或非标格式,TO_TIMESTAMP是唯一选择 - 性能上,
CAST最快,TO_TIMESTAMP因需解析格式模板略慢,但在大多数业务场景中差异可忽略
常见错误排查:为什么返回 NULL 或报错?
TO_TIMESTAMP 在输入字符串与格式模板不匹配时,**默认行为是抛异常**,不是返回 NULL。如果你看到 NULL,大概率是外层用了 COALESCE 或触发了隐式类型转换陷阱。
- 检查字符串是否含不可见字符(如 BOM、全角空格),可用
LENGTH()和HEX()辅助诊断 - 模板中用了
FM修饰符(如"FMMM")却传入带前导零的数字(如'05'),会导致解析失败 - 年份位数不一致:模板写
YYYY但字符串给'24',或反过来,都会报错 - 使用
TO_TIMESTAMP(NULL, ...)会返回 NULL,但这是输入为空,不是函数容错机制
真正难调试的是格式模板和字符串的“肉眼相似但逻辑不等价”,比如 "DD.MM.YYYY" 和 "DD/MM/YYYY" 差一个字符,结果天差地别。











