MySQL用FROM_UNIXTIME()转时间戳,秒级直接转换、毫秒级需除1000;PostgreSQL用TO_TIMESTAMP(),毫秒级须用/1000.0避免截断;SQLite用datetime(ts,'unixepoch'),毫秒级需先转秒字符串;三者时区处理与精度规则各异,无跨库兼容写法。

MySQL 中用 FROM_UNIXTIME() 转时间戳为可读日期
MySQL 存储的时间戳通常是整数(秒级或毫秒级),直接 SELECT 只能看到数字。要用指定格式显示,必须用 FROM_UNIXTIME() 转成 datetime 类型,再配合 DATE_FORMAT() 格式化。
常见错误是直接对时间戳字段用 DATE_FORMAT(ts_col, '%Y-%m-%d') —— 这会失败,因为 DATE_FORMAT() 只接受 DATETIME 或 DATE 类型,不认整数时间戳。
- 秒级时间戳(10 位):直接用
FROM_UNIXTIME(ts_col) - 毫秒级时间戳(13 位):先除以 1000,再转,如
FROM_UNIXTIME(ts_col / 1000) - 常用格式示例:
DATE_FORMAT(FROM_UNIXTIME(ts_col), '%Y年%m月%d日 %H:%i')→2024年05月22日 14:30 - 注意时区:
FROM_UNIXTIME()默认按 MySQL 服务器时区解析,若数据是 UTC 时间但服务器在东八区,结果会偏移 8 小时
PostgreSQL 中用 TO_TIMESTAMP() + TO_CHAR()
PostgreSQL 没有原生“时间戳整数”类型,所以必须显式转换。秒级用 TO_TIMESTAMP(ts_col),毫秒级则要先转成秒(ts_col / 1000.0),否则会当成微秒处理(导致结果错乱近 30 年)。
- 秒级转换:
TO_CHAR(TO_TIMESTAMP(ts_col), 'YYYY-MM-DD HH24:MI:SS') - 毫秒级务必写
TO_TIMESTAMP(ts_col / 1000.0),不能只写/ 1000(整数除法会截断小数) -
TO_CHAR()的格式符大小写敏感:MM是月份,mi是分钟,Mi会报错 - 时区更可控:可在
TO_TIMESTAMP()后链式调用AT TIME ZONE 'UTC'显式指定输入时区
SQLite 中没有内置时间戳函数,得靠 datetime() 和修饰符
SQLite 的 datetime() 函数本身支持 Unix 时间戳(秒级),但只接受整数或字符串形式的秒数。它不识别毫秒值,也不直接支持格式化,需靠修饰符拼接。
- 秒级时间戳:直接
datetime(ts_col, 'unixepoch') - 毫秒级必须先转成秒字符串,例如
datetime(CAST(ts_col / 1000 AS TEXT), 'unixepoch') - 加时区偏移:用
datetime(ts_col, 'unixepoch', '+8 hours')补东八区,但注意这是“结果加偏移”,不是“按该时区解析原始时间戳” - 无法直接控制输出格式(如去掉秒),只能靠字符串函数截取,比如
SUBSTR(datetime(ts_col, 'unixepoch'), 1, 10)取日期部分
跨数据库兼容写法几乎不存在,别硬套一个 SQL 到所有库
各数据库对时间戳的类型假设、精度处理、时区默认行为完全不同。比如同样传入 1716383400:
- MySQL 的
FROM_UNIXTIME()当作秒,正确解析 - PostgreSQL 的
TO_TIMESTAMP(1716383400)也当秒,但TO_TIMESTAMP(1716383400000)会被当作微秒(≈ year 56359) - SQLite 的
datetime(1716383400, 'unixepoch')正确,但datetime(1716383400000, 'unixepoch')直接返回NULL
最易被忽略的是毫秒时间戳的单位误判——开发本地用 MySQL 测试没问题,上线到 PostgreSQL 就出怪时间,往往卡在除不除 1000.0 这一步。

















