NOW() 返回带时分秒的DATETIME类型当前时间,CURDATE()仅返回DATE类型日期部分;二者精度与用途不同,误用会导致查询遗漏或计算错误。

MySQL 里 NOW() 和 CURDATE() 到底返回什么?
它们都返回当前时间,但精度和类型不同:NOW() 返回带时分秒的 DATETIME(如 '2024-05-12 14:23:08'),CURDATE() 只返回日期部分 DATE(如 '2024-05-12')。别用 CURDATE() 去比对带时间的字段,会漏掉当天后半天的数据。
- 查今天所有订单,用
WHERE order_time >= CURDATE()是错的——CURDATE()被隐式转成'2024-05-12 00:00:00',但实际想覆盖全天,应写WHERE order_time >= '2024-05-12' AND order_time 或更安全地用 <code>WHERE DATE(order_time) = CURDATE()(注意:这会让order_time索引失效) -
NOW()在一个语句内多次调用,返回值完全一致;但在不同语句或事务中可能不同 - 如果只要年月日,
CURDATE()比DATE(NOW())少一次函数调用,性能略优
DATE_FORMAT() 格式化时为什么总少一位或乱码?
常见问题不是语法错,而是格式符大小写敏感、且不支持中文占位符。比如 %Y 是 4 位年,%y 是 2 位;%m 是补零月,%c 是不补零月——混用会导致输出异常。
- 想输出 “2024年05月12日”,必须写
DATE_FORMAT(NOW(), '%Y年%m月%d日');写成'%Y年%M月%D日'会把%M(英文月份名)和%D(带序数词的日期,如 1st)直接当字符串输出,结果是'2024年May月12th日' - 格式符里不能加空格以外的不可见字符,复制粘贴时容易带入全角空格或 Zero Width Space,导致 SQL 报错
ERROR 1582 (42000): Incorrect parameter count in the call to native function 'DATE_FORMAT' - 如果字段本身是
TIMESTAMP,且时区设置为+00:00,而你本地是东八区,DATE_FORMAT(created_at, '%H:%i')显示的可能是 UTC 时间,不是你预期的“北京时间”
DATEDIFF() 算天数为什么结果总是负的?
DATEDIFF(a, b) 的含义是 “a 减 b”,即 a - b 的天数差。顺序反了,结果就是负数。它只计算日期部分,自动忽略时分秒——这点常被忽略,导致逻辑偏差。
- 查“注册超过 7 天的用户”,要写
WHERE DATEDIFF(CURDATE(), register_date) > 7,不是DATEDIFF(register_date, CURDATE()) -
DATEDIFF('2024-05-12 23:59:59', '2024-05-12 00:00:01')结果是0,因为只取日期部分比较 - 如果需要精确到小时或分钟的差值,别硬套
DATEDIFF(),改用TIMESTAMPDIFF(HOUR, a, b)或TIMESTAMPDIFF(MINUTE, a, b)
跨时区存取时间时,NOW() 和系统时间到底以谁为准?
MySQL 的 NOW() 返回的是服务器当前时区的时间,不是客户端所在时区。如果你的服务器在 UTC,应用在东八区,直接用 NOW() 存时间,再用 DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i') 查,看到的就是 UTC 时间,而非用户本地时间。
- 建表时若用
TIMESTAMP类型,它会自动按服务器时区存、按连接时区取;而DATETIME是“所见即所得”,存啥取啥,不转换 - 连接建立后,可通过
SET time_zone = '+08:00'临时切换当前会话时区,之后NOW()和TIMESTAMP字段读取都会按 +08:00 解析 - 线上部署务必确认
my.cnf中的default-time-zone设置,或在应用层统一用 UTC 存储、业务层转换显示,避免各处时区逻辑打架
事情说清了就结束。时区、精度、函数参数顺序,这三个点,错一个就查半天。










