FROM_UNIXTIME只接受秒级整数,输入毫秒值(如1717023600000)会导致年份错乱(如显示为56379年),正确做法是先除以1000取整;格式化字符串需加单引号;WHERE条件中应避免对时间戳字段使用FROM_UNIXTIME,改用UNIX_TIMESTAMP转换日期进行比较。

FROM_UNIXTIME 只接受秒级整数,直接传入毫秒值(如 1717023600000)会导致年份错乱(比如显示为公元 56379 年),不是函数“不工作”,而是单位理解错了。
FROM_UNIXTIME 为什么返回奇怪年份?
典型错误现象:输入 1717023600000 得到 '56379-04-28 12:40:00' 这类远超预期的结果。
根本原因是 FROM_UNIXTIME 严格按“秒”解析——它把 1717023600000 当作“距 1970 年过了 1.7 万亿秒”,而非“毫秒”。
- 正确做法:先除以 1000,再取整:
FROM_UNIXTIME(FLOOR(1717023600000 / 1000)) - 如果字段是
BIGINT存毫秒值,必须写成FROM_UNIXTIME(ts_ms / 1000),不能省略除法 - 用
CAST(ts_ms AS UNSIGNED) / 1000也行,但FLOOR更明确表达“截断小数”意图
格式化字符串必须加单引号
常见报错 ERROR 1064 (42000) 往往不是语法问题,只是漏了引号。
- 错误写法:
FROM_UNIXTIME(1717023600, %Y-%m-%d)——%Y被当变量名,MySQL 找不到定义 - 正确写法:
FROM_UNIXTIME(1717023600, '%Y-%m-%d') - 注意字母
i表示分(minute),不是数字1;H是 24 小时制,h是 12 小时制
WHERE 条件里别对时间戳字段用 FROM_UNIXTIME
写 WHERE FROM_UNIXTIME(created_ts) > '2024-01-01' 看似直观,但会让 created_ts 字段的索引完全失效。
- 正确做法:把日期转回时间戳比较:
WHERE created_ts > UNIX_TIMESTAMP('2024-01-01') - 如果字段存的是毫秒值,记得同步换算:
WHERE ts_ms > UNIX_TIMESTAMP('2024-01-01') * 1000 - 想按天查?别用
FROM_UNIXTIME(ts, '%Y-%m-%d') = '2024-05-24',改用范围查询:WHERE ts >= UNIX_TIMESTAMP('2024-05-24') AND ts
时区偏差比想象中更隐蔽
FROM_UNIXTIME 不读系统本地时间,只认 MySQL 会话时区。服务器设为 '+00:00',而你传入的是东八区生成的时间戳,结果就晚 8 小时。
- 查当前会话时区:
SELECT @@session.time_zone; - 临时切时区更可靠:
SET time_zone = '+08:00'; SELECT FROM_UNIXTIME(1717023600); - 跨时区场景推荐统一存 UTC 时间戳,查时显式转:
FROM_UNIXTIME(ts, '+08:00')—— 第二个参数必须是带符号字符串,不能写'CST'或'Asia/Shanghai'
真正容易被忽略的是:即使你加了 FLOOR 和引号、也设了时区,只要在 WHERE 里对时间戳列套函数,索引就废了。性能问题往往在数据量上来后才暴露,而不是语法报错时。


















