MySQL中FROM_UNIXTIME()将Unix时间戳转为可读日期,默认格式YYYY-MM-DD HH:MM:SS;需注意空值、非数字输入、毫秒处理、时区指定(推荐'+08:00')、避免WHERE中函数包裹字段导致索引失效。

MySQL里用 FROM_UNIXTIME() 转时间戳
Unix时间戳是整数,比如 1717027200,直接查出来没法读。MySQL原生支持转成可读日期,核心函数就是 FROM_UNIXTIME()。它默认输出 YYYY-MM-DD HH:MM:SS 格式,和 DATETIME 类型完全兼容。
常见错误是传入空值或非数字字段——FROM_UNIXTIME(NULL) 返回 NULL,而 FROM_UNIXTIME('abc') 会静默转成 1970-01-01 08:00:00(即 Unix epoch 起点),容易埋下数据异常隐患。
- 确保字段类型是
INT或BIGINT,且值在合理范围(如 1970–2106 年对应 0–2147483647) - 如果时间戳单位是毫秒(常见于前端 JS
Date.now()),先除以 1000:FROM_UNIXTIME(ts_column / 1000) - 想转成日期字符串而非 DATETIME 类型,可以套一层
DATE():DATE(FROM_UNIXTIME(ts_column))
指定时区用 FROM_UNIXTIME(ts, timezone)
MySQL 默认按系统时区解析时间戳,但很多业务数据库跑在 UTC 服务器上,而业务要求显示东八区时间。这时不能靠改系统时区,得在函数里显式指定。
第二个参数接受时区偏移或命名时区,例如:FROM_UNIXTIME(1717027200, '+08:00') 或 FROM_UNIXTIME(1717027200, 'Asia/Shanghai')。注意:后者依赖 MySQL 的时区表是否已加载(需执行 mysql_tzinfo_to_sql 导入)。
- 用偏移量(如
'+08:00')最稳妥,不依赖外部时区数据 - 如果连接层已设好时区(
SET time_zone = '+08:00'),FROM_UNIXTIME()也会受其影响,但显式传参优先级更高 - 别混淆
CONVERT_TZ():它用于已有 DATETIME 值的时区转换,不是从时间戳开始的
格式化输出用 DATE_FORMAT(FROM_UNIXTIME(...), ...)
有时候不需要完整时间,只要“2024-05-30”或“30/May/2024”。这时候不能只靠 FROM_UNIXTIME(),得嵌套 DATE_FORMAT()。
例如:DATE_FORMAT(FROM_UNIXTIME(1717027200), '%Y-%m-%d') 输出 2024-05-30;DATE_FORMAT(FROM_UNIXTIME(1717027200), '%d/%b/%Y') 输出 30/May/2024。格式符大小写敏感,%b 是英文缩写,%M 是全称。
- 避免在 WHERE 条件里用
DATE_FORMAT()包裹字段——这会让索引失效,应先用FROM_UNIXTIME()转成日期再比较 - 中文月份、星期需配合
SET lc_time_names = 'zh_CN',否则%M仍输出英文 - 如果只是取年月日,
FROM_UNIXTIME(ts, '%Y-%m-%d')这种简写也行,但可读性不如嵌套清晰
WHERE 条件中正确比较时间戳字段
最容易出错的是:想查“今天的数据”,却写成 WHERE FROM_UNIXTIME(create_ts) >= CURDATE()。这会导致全表扫描,因为函数作用于字段,无法走索引。
正确做法是把标准日期反向转成时间戳范围。例如查 2024-05-30 当天:WHERE create_ts BETWEEN UNIX_TIMESTAMP('2024-05-30') AND UNIX_TIMESTAMP('2024-05-30 23:59:59')。更安全的写法是用开区间:WHERE create_ts >= UNIX_TIMESTAMP('2024-05-30') AND create_ts 。
-
UNIX_TIMESTAMP()不传参时返回当前时间戳,传日期字符串时按服务器时区解析 - 如果字段本身是
DATETIME类型,就别用时间戳逻辑了——直接用DATE(create_time) = '2024-05-30',但注意同样有索引风险 - 时间戳字段建索引有效,但一定要确保查询条件没对它做函数运算


















