date_format()用于自定义格式化日期时间,需传入日期值和含%前缀的格式符(如%y、%m);输入为null或非法日期时返回null;避免在where中使用以防索引失效。

DATE_FORMAT函数的基本用法和常见格式符
MySQL里想按自定义样式显示日期时间,DATE_FORMAT() 是最直接的方案。它接收两个参数:一个日期时间值(如 created_at 字段),和一个格式化字符串。格式符必须用百分号开头,比如 %Y 表示4位年份,%m 是补零的月份,%d 是补零的日期。
容易踩的坑是把格式符写成 YYYY-MM-DD 这种纯文本形式——这不会被解析,得写成 '%Y-%m-%d' 才生效。
-
%Y和%y区别明显:%Y输出 2024,%y只输出 24 - 小时要注意 12 小时制和 24 小时制:
%h(01–12)和%H(00–23)不能混用 - 秒用
%s(补零两位),毫秒要用%f(6 位数字),但注意%f在DATE_FORMAT()中仅对包含微秒的DATETIME(6)有效
在SELECT查询中直接格式化输出
最常用场景就是查数据时顺手转格式,避免应用层再处理。只要字段本身是 DATETIME、TIMESTAMP 或能隐式转为日期的字符串,就能传给 DATE_FORMAT()。
例如想查出“2024年05月21日 14:30”这种中文风格:
SELECT DATE_FORMAT(created_at, '%Y年%m月%d日 %H:%i') AS formatted_time FROM orders;
注意:如果 created_at 是 NULL,整个 DATE_FORMAT() 结果也是 NULL,不会报错但可能影响前端展示逻辑。
- 别在
WHERE子句里对字段用DATE_FORMAT()做条件过滤——这会让索引失效,应改用DATE()、BETWEEN等可走索引的方式 - 格式化后的结果是字符串类型,不能再参与时间计算(比如加减 INTERVAL),需要先用
STR_TO_DATE()转回去 - 如果字段是
TIMESTAMP且涉及时区,DATE_FORMAT()按当前会话时区输出,不是存储时的 UTC 值
与NOW()、CURDATE()等函数组合使用
除了格式化已有字段,也常用来美化当前时间或构造固定格式的默认值。比如生成带时间戳的订单编号前缀:
SELECT CONCAT('ORD-', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s')) AS order_no;
这里 NOW() 返回的是当前会话时区的时间,不是服务器系统时间;若数据库启用了 explicit_defaults_for_timestamp,行为还可能受 SQL mode 影响。
-
CURDATE()和CURTIME()分别只返回日期或时间部分,若只需要日期格式(如'2024-05-21'),用DATE_FORMAT(CURDATE(), '%Y-%m-%d')比嵌套更清晰 - 避免用
DATE_FORMAT(UNIX_TIMESTAMP(), ...)——UNIX_TIMESTAMP()返回整数,不是日期类型,会导致DATE_FORMAT()返回NULL - 在 INSERT 或 UPDATE 语句中用
DATE_FORMAT(NOW(), ...)写入,存进去的就是字符串,不再是时间类型,慎用
格式化结果为空或报错的典型原因
执行 DATE_FORMAT() 后得到空字符串或 NULL,大概率不是函数写错了,而是输入值本身有问题。
- 输入是非法日期字符串(如
'2024-02-30'或'abc'),MySQL 会静默转成NULL,再经DATE_FORMAT()输出NULL - 字段定义为
DATE类型却插入了带时间部分的值(如'2024-05-21 14:30:00'),MySQL 截断后可能存成'0000-00-00',而这个值被视作非法日期,DATE_FORMAT()处理时返回NULL - 格式字符串里多写了未被识别的字符(比如误写成
'%YYYY'),MySQL 会原样输出未识别部分,但已识别的格式符仍生效,容易造成混淆
真正难调试的是隐式类型转换问题——比如把 INT 当日期传进去,MySQL 可能尝试解析成年份,也可能直接返回 NULL,得用 IS NULL 或 COALESCE() 做兜底。











