MySQL中用DATE_FORMAT()格式化日期时间,需用%开头的占位符(如%Y、%m),不可用Java风格;CAST/CONVERT仅转类型,无法自定义格式;WHERE中对字段用DATE_FORMAT会使索引失效。

MySQL中用DATE_FORMAT()控制日期时间字符串格式
直接用 DATE_FORMAT() 函数,它是 MySQL 里最可控、最常用的日期格式化工具。它接收两个参数:一个日期时间值(如 NOW()、created_at 字段),和一个格式化模板字符串。
模板里用特定占位符表示年月日时分秒等,比如 %Y 是 4 位年份,%m 是补零月份,%d 是补零日期。注意大小写敏感,%y 是两位年份,%Y 才是四位。
常见错误是把模板写成 "YYYY-MM-DD" 这种类 Java 风格——MySQL 不认,必须用 % 开头的标识符。
-
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');→2024-06-15 14:23:05 -
SELECT DATE_FORMAT('2023-01-01 09:30:45', '%d/%m/%Y %p %h:%i');→01/01/2023 AM 09:30 - 字段查询:
SELECT id, DATE_FORMAT(updated_at, '%b %e, %Y') AS formatted_date FROM posts;
为什么不用CAST()或CONVERT()转字符串
CAST(created_at AS CHAR) 或 CONVERT(created_at, CHAR) 会走默认格式(通常是 'YYYY-MM-DD HH:MM:SS'),无法自定义分隔符、顺序或本地化内容(比如英文月份名)。它们只是类型转换,不是格式化工具。
在需要 ISO 标准格式(如 20240615T142305)或带中文(如 2024年06月15日)时,CAST 完全无能为力。
- 想输出
2024年06月15日?只能用DATE_FORMAT(dt, '%Y年%m月%d日') - 想省略秒、只保留到分钟?
%Y-%m-%d %H:%i即可,CAST没法截断 - 性能上差别不大,但语义明确性差很多:用
CAST是“我只要字符串”,用DATE_FORMAT是“我要这个样子的字符串”
DATE_FORMAT()对索引和WHERE条件的影响
在 WHERE 子句里对字段用 DATE_FORMAT(created_at, '%Y-%m') 做筛选,会导致该字段索引失效——因为函数作用于列,MySQL 无法用 B+ 树直接定位。
例如:WHERE DATE_FORMAT(created_at, '%Y-%m') = '2024-06' 会触发全表扫描;应改写为范围查询:WHERE created_at >= '2024-06-01' AND created_at 。
- 格式化只应在
SELECT列表或应用层做,避免出现在WHERE/ORDER BY(除非你确认不需要走索引) - 如果必须按格式分组(如按“年月”统计),可用
GROUP BY YEAR(created_at), MONTH(created_at)替代DATE_FORMAT,更高效 -
DATE_FORMAT()返回的是字符串类型,不能直接参与日期运算(如+ INTERVAL 1 DAY),需先用STR_TO_DATE()转回日期
时区和系统变量会影响DATE_FORMAT()结果吗
不影响格式模板本身,但影响输入值的“实际含义”。DATE_FORMAT() 只是按给定时间值套模板,不主动做时区转换。
如果你传入的是 TIMESTAMP 类型字段,它在存储时已按当前会话时区转为 UTC,读取时再转回会话时区——所以最终格式化的,是会话时区下的那个时间点。
- 检查当前时区:
SELECT @@time_zone;(可能返回SYSTEM或具体时区如'+08:00') - 临时切换:
SET time_zone = '+00:00';,再执行DATE_FORMAT(NOW(), ...)就得到 UTC 时间的格式化结果 - 若字段是
DATETIME类型,则完全不受时区影响,存啥格式化啥
DATE_FORMAT() 的值,已经是业务逻辑所需的时区和精度——否则再漂亮的格式也是错的。


















