from_unixtime将秒级unix时间戳转为datetime,默认按系统时区解析;支持格式化输出、需处理毫秒截断、null/非法输入返回null,且避免在索引字段直接使用。

FROM_UNIXTIME 函数的基本用法
FROM_UNIXTIME 是 MySQL 中将 Unix 时间戳(秒级整数)转为可读日期时间的内置函数。它默认返回 DATETIME 类型,格式为 'YYYY-MM-DD HH:MM:SS'。直接传入一个合法时间戳即可,比如:FROM_UNIXTIME(1717027200) 返回 '2024-05-30 00:00:00'。
注意:该函数只接受秒级时间戳(10 位数字),不支持毫秒(13 位)。若你拿到的是毫秒时间戳(如 JavaScript 的 Date.now()),必须先除以 1000 并用 FLOOR() 或 CAST(... AS UNSIGNED) 截断小数,否则会出错或返回 NULL。
指定输出格式:用第二个参数控制日期样式
FROM_UNIXTIME 支持第二个可选参数,是一个格式化字符串,类似 DATE_FORMAT 的语法。例如:FROM_UNIXTIME(1717027200, '%Y年%m月%d日') 返回 '2024年05月30日'。
- 常用格式符:
%Y(4 位年)、%m(补零月)、%d(补零日)、%H(24 小时制)、%i(分钟)、%s(秒) - 如果传入的格式字符串非法(如拼错成
%k),函数不会报错,而是原样返回格式串本身(比如返回文字'%k'),容易误判为成功 - 格式化结果是
STRING类型,不能再直接参与日期计算;如需后续比较,应先用STR_TO_DATE转回日期类型
时区问题:FROM_UNIXTIME 默认使用系统时区
FROM_UNIXTIME 解析时间戳时,始终按 MySQL 服务器当前时区解释。比如服务器设为 +08:00,那么 FROM_UNIXTIME(0) 返回的是 '1970-01-01 08:00:00',而非 UTC 的 '1970-01-01 00:00:00'。
如果你需要固定按 UTC 输出,有两个办法:
- 临时切换会话时区:
SET time_zone = '+00:00'; SELECT FROM_UNIXTIME(0); - 用
CONVERT_TZ转换:CONVERT_TZ(FROM_UNIXTIME(0), @@session.time_zone, '+00:00')—— 但注意这本质是“把本地时间转成 UTC”,不是“把时间戳按 UTC 解释” - 更稳妥的做法是:存储时间戳时就明确业务时区意图,查询时统一用
UTC_TIMESTAMP()+UNIX_TIMESTAMP()配合处理
NULL 和非法输入的处理边界
当传入 NULL、负数、非数字或超出范围值(如大于 2147483647 的 32 位上限),FROM_UNIXTIME 直接返回 NULL,且不会报错。这在 JOIN 或 WHERE 条件中容易引发静默过滤。
排查建议:
- 用
IS NULL显式检查:WHERE FROM_UNIXTIME(created_at) IS NOT NULL - 提前清洗数据:
WHERE created_at BETWEEN 0 AND 2147483647 - 避免在索引字段上直接套用
FROM_UNIXTIME做条件查询,会导致全表扫描;应改用UNIX_TIMESTAMP('2024-01-01')反向计算时间戳范围
真正麻烦的是那些看似合理实则无效的时间戳——比如 1717027200.5(带小数)会被截断为 1717027200,而 'abc' 这种字符串会转成 0 再解析为 '1970-01-01 08:00:00',这种隐式转换很难一眼发现。











