MySQL用FROM_UNIXTIME()转时间戳,返回默认格式字符串;PostgreSQL需TO_TIMESTAMP()配合TO_CHAR(),注意毫秒需除1000;SQLite用datetime()或strftime()并指定'unixepoch';跨库无通用写法,推荐应用层转换。

MySQL里用FROM_UNIXTIME()转时间戳
MySQL原生支持Unix时间戳转日期,FROM_UNIXTIME()是首选函数。它默认返回'Y-m-d H:i:s'格式的字符串,可直接用于展示或排序。
常见错误是传入NULL或非数字值,这时函数返回NULL,查不出结果却没报错,容易误判数据为空。另外注意时区:该函数按MySQL服务器当前时区解析,不是UTC——如果时间戳本身是UTC生成的,而服务器在东八区,结果会多出8小时。
- 基础用法:
SELECT FROM_UNIXTIME(1717027200)→'2024-05-30 00:00:00' - 指定格式:
FROM_UNIXTIME(1717027200, '%Y年%m月%d日')→'2024年05月30日' - 处理可能为NULL的字段:
COALESCE(FROM_UNIXTIME(created_at), '未知')
PostgreSQL必须用TO_TIMESTAMP() + 类型转换
PostgreSQL不认FROM_UNIXTIME(),得用TO_TIMESTAMP(),而且它返回的是TIMESTAMP WITH TIME ZONE类型,不是字符串。想输出成可读格式,还得套一层TO_CHAR()。
容易踩的坑是忘记单位:PostgreSQL的TO_TIMESTAMP()默认把输入当秒数,但如果时间戳是毫秒级(比如JavaScript的Date.now()),必须先除以1000,否则会得到公元3世纪的日期。
- 秒级时间戳:
SELECT TO_CHAR(TO_TIMESTAMP(1717027200), 'YYYY-MM-DD HH24:MI:SS') - 毫秒级时间戳:
TO_TIMESTAMP(1717027200000 / 1000.0)(注意用1000.0避免整除截断) - 强制转为本地时区显示:
AT TIME ZONE 'Asia/Shanghai'加在TO_TIMESTAMP()后面
SQLite没有内置时间戳函数,靠datetime()硬凑
SQLite的datetime()函数能解析Unix时间戳,但只接受秒级整数,且必须显式声明单位'unixepoch'。漏写这个参数,它会把数字当成儒略日,结果完全不对。
另一个限制是不支持自定义格式化——datetime()固定输出YYYY-MM-DD HH:MM:SS。如果要“2024/05/30”这种格式,只能用strftime()替代,且同样要带'unixepoch'。
- 标准转换:
SELECT datetime(1717027200, 'unixepoch') - 自定义格式:
strftime('%Y/%m/%d', 1717027200, 'unixepoch') - 时区偏移(如UTC+8):
datetime(1717027200, 'unixepoch', '+8 hours')
跨数据库兼容写法几乎不存在,别硬套
想写一条SQL在MySQL、PostgreSQL、SQLite里都跑通?基本做不到。FROM_UNIXTIME()、TO_TIMESTAMP()、datetime(..., 'unixepoch')三者语法和语义差异太大,连参数个数都不一样。强行抽象成视图或函数,反而增加维护成本和隐性bug风险。
真正可行的做法是:在应用层判断数据库类型,动态拼接对应函数;或者统一在代码里做转换(比如PHP用date(),Python用datetime.fromtimestamp()),SQL只负责取原始时间戳。后者更可控,尤其当涉及夏令时、时区切换等复杂场景时。

















