导读:本期聚焦于勇士创作的《如何在MySQL中进行日期计算?常用日期函数详解与实战示例》,敬请观看详情。为什么同样的日期计算需求,有人写了一堆复杂逻辑,有人一行SQL就能搞定?MySQL内置了丰富的日期函数,掌握它们可以大幅简化开发工作。本文围绕MySQL日期计算展开,详细介绍DATE_ADD与DATE_SUB实现日期加减、DATEDIFF与TIMESTAMPDIFF计算时间差、DATE_FORMAT与日期提取函数的使用方式,并针对实际业务场景给出获取本月第一天、近七天数据、年龄计算等常见案例,同时分享日期运算中的格式陷阱与性能注意事项,帮助你写出更简洁高效的日期查询语句。

日期计算几乎是所有业务系统都绕不开的需求:统计近七天的订单、计算用户年龄、获取本月第一天、判断会员是否到期,这些场景都需要对日期进行加减和比较。不少开发者习惯把日期取出来放到应用程序里用代码计算,再拼回SQL查询,结果SQL越写越复杂,性能也随之下降。其实MySQL本身提供了非常完善的日期计算函数,绝大多数需求一行SQL就能解决。本文将系统梳理这些函数的用法,并结合实际业务场景给出可直接套用的示例。

如何在MySQL中进行日期计算?常用日期函数详解与实战示例

一、日期加减:DATE_ADD与DATE_SUB

DATE_ADD和DATE_SUB是MySQL中做日期加减最核心的两个函数。DATE_ADD用于在日期上增加一个时间间隔,DATE_SUB则用于减去一个时间间隔。两个函数的语法完全一致,只是方向相反。

它们的第一个参数是日期值,第二个参数是一个INTERVAL表达式,格式为INTERVAL 数量 单位。单位非常丰富,包括SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER、YEAR,甚至还有组合单位如DAY_HOUR、YEAR_MONTH等。下面看几个典型用法:

-- 当前时间加3天
SELECT DATE_ADD(NOW(), INTERVAL 3 DAY);

-- 指定日期减2个月
SELECT DATE_SUB('2024-08-15', INTERVAL 2 MONTH);

-- 加1年零3个月
SELECT DATE_ADD('2024-01-31', INTERVAL '1-3' YEAR_MONTH);

-- 计算七天的截止时间
SELECT DATE_ADD(CURDATE(), INTERVAL 6 DAY);

需要注意一个细节:当对月末日期做加减时,MySQL会自动处理溢出问题。例如DATE_ADD('2024-01-31', INTERVAL 1 MONTH)的结果是2024-02-29,因为2024年是闰年,MySQL会将结果截断到该月最后一天,而不是报错或产生3月1日。这个行为在大多数业务中是符合预期的,但如果涉及账单周期这类对边界敏感的逻辑,务必提前测试。

另外,MySQL支持用+ INTERVAL 3 DAY这种简写形式替代DATE_ADD,例如SELECT NOW() + INTERVAL 3 DAY,效果完全相同,写起来更简洁。但为了代码可读性和跨版本兼容性,建议在正式项目中统一使用标准函数写法。

二、时间差计算:DATEDIFF、TIMESTAMPDIFF与TIME_TO_SEC

计算两个日期之间相差多少,是另一个高频需求。MySQL提供了几个侧重点不同的函数,用错会得到意想不到的结果。

DATEDIFF(date1, date2)返回两个日期之间相差的天数,只比较日期部分,忽略时分秒。它的计算逻辑是date1减date2,参数顺序不能搞反。比如DATEDIFF('2024-08-10', '2024-08-01')返回9,而反过来则是-9。这个函数非常适合判断两个日期是否在同一天、相差几天这类场景。

如果需要更精确的时间差,比如相差多少小时、多少分钟,就要用TIMESTAMPDIFF(unit, datetime1, datetime2)。它的第一个参数指定返回结果的单位,可以是SECOND、MINUTE、HOUR、DAY、MONTH、YEAR等。注意它的参数顺序与DATEDIFF相反,是后面减前面。看下面的对比:

-- 返回相差天数(忽略时间部分)
SELECT DATEDIFF('2024-08-10 23:00:00', '2024-08-01 00:30:00'); -- 9

-- 返回相差的小时数
SELECT TIMESTAMPDIFF(HOUR, '2024-08-01 08:00:00', '2024-08-02 10:30:00'); -- 26

-- 返回相差的秒数
SELECT TIMESTAMPDIFF(SECOND, '2024-08-01 08:00:00', '2024-08-01 08:05:30'); -- 330

-- 计算年龄:满周岁才算1年
SELECT TIMESTAMPDIFF(YEAR, '1995-06-15', CURDATE());

这里要特别提醒TIMESTAMPDIFF的一个特性:它返回的是完整单位的数量。也就是说,用YEAR单位计算年龄时,只有过了生日才会进位,这正好符合日常生活中满周岁才算几岁的习惯。而如果用YEAR函数相减来算年龄,就会出现生日未到也算大一岁的问题,这是很多新手容易踩的坑。

此外还有一个PERIOD_DIFF(P1, P2)函数用于计算两个年月之间相差的月数,参数格式是YYYYMM或YYMM,例如PERIOD_DIFF(202408, 202401)返回7,在按月统计的场景偶尔会用到。

三、日期提取与格式化:YEAR、MONTH、DAY与DATE_FORMAT

做日期计算之前,往往需要先从日期中提取出年、月、日、星期等部分。MySQL提供了一组提取函数:YEAR()返回年份,MONTH()返回月份数字,DAYOFMONTH()返回几号,DAYOFWEEK()返回星期几(1表示周日),WEEKDAY()也返回星期几(0表示周一),DAYOFYEAR()返回一年中的第几天。这些函数组合起来可以应对大多数提取需求。

DATE_FORMAT(date, format)则是格式化输出的利器。它按照指定的格式字符串把日期转成想要的样式,常用格式符包括%Y四位年份、%m两位月份、%d两位日期、%H小时、%i分钟、%s秒、%W完整英文星期名等。通过它还能巧妙地实现一些计算需求,比如获取本月第一天:

-- 获取本月第一天
SELECT DATE_FORMAT(CURDATE(), '%Y-%m-01');

-- 获取上个月的第一天和最后一天
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') AS first_day,
       LAST_DAY(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AS last_day;

-- 查询本周的数据(周一为一周开始)
SELECT * FROM orders
WHERE YEARWEEK(create_time, 1) = YEARWEEK(NOW(), 1);

-- 按月分组统计订单量
SELECT DATE_FORMAT(create_time, '%Y-%m') AS month, COUNT(*) AS total
FROM orders
GROUP BY month
ORDER BY month;

上面的例子中出现了LAST_DAY()函数,它返回指定日期所在月的最后一天,配合DATE_ADD可以算出下个月第一天的日期:DATE_ADD(LAST_DAY(CURDATE()), INTERVAL 1 DAY)。YEARWEEK()则返回年份加周数的组合数字,第二个参数传1表示以周一为每周第一天,用来查询本周数据非常方便。

四、实战场景:常见业务日期查询模板

掌握了基础函数之后,来看几个可以直接套用的业务查询模板。第一个是统计近七天的数据,注意这里的近七天应该包含今天,所以条件是大于等于六天前的零点:

-- 近七天(含今天)
SELECT * FROM orders
WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
  AND create_time < DATE_ADD(CURDATE(), INTERVAL 1 DAY);

-- 今天的数据
SELECT * FROM orders
WHERE create_time >= CURDATE()
  AND create_time < DATE_ADD(CURDATE(), INTERVAL 1 DAY);

这里有一个重要的性能技巧:不要对字段使用函数。如果把条件写成WHERE DATE(create_time) = CURDATE(),虽然结果一样,但对create_time列使用函数会导致索引失效,全表扫描。正确做法是把计算转移到常量一侧,让字段保持裸列状态,这样才能走索引。这个原则适用于所有日期查询。

第二个场景是判断时间是否在某个区间内,例如查询正在进行中的活动:

SELECT * FROM activities
WHERE NOW() BETWEEN start_time AND end_time;

BETWEEN语法在日期比较中天然可用,因为日期和日期时间在MySQL中都是可以比较的类型。但要避免用字符串直接拼接比较,比如把日期格式化成字符串后再用LIKE匹配,这种写法既低效又容易出错。

五、日期计算中的常见陷阱

最后总结几个容易出错的地方。第一是日期格式问题:MySQL默认接受的日期字符串格式是YYYY-MM-DD或YYYY-MM-DD HH:MM:SS,如果插入中文格式的日期字符串如2024年8月1日,会直接报错或产生警告。存入数据库前务必保证格式正确。

第二是NULL值的处理。所有日期函数遇到NULL参数都会返回NULL,如果在做日期加减时字段可能为空,要么在查询前用IFNULL()做默认值兜底,要么在WHERE条件中排除NULL行,否则可能得到错误的对账结果。

第三是时区问题。NOW()和CURDATE()返回的是服务器时区的时间,如果应用服务器与数据库服务器时区不一致,或者业务需要跨时区支持,就要考虑使用UTC时间存储,或者通过SET time_zone统一会话时区,避免统计口径出现偏差。

第四是零值日期。在严格模式下,0000-00-00这样的零值日期无法直接插入或参与计算,遇到历史数据中存在零值的情况,需要先清洗数据再做日期运算,否则查询会直接报错。

总的来说,MySQL的日期函数体系相当完善,从简单的加减、差值计算到格式化、区间判断都有对应方案。写日期相关SQL时记住两个原则:能用数据库算的就不要搬到应用层算,能用常量计算的就不要对字段套函数。把这两点落实到位,日期查询的代码量和执行效率都会有明显改善。

mysql日期计算DATE_ADDDATEDIFF修改时间:2026-09-16 05:58:43

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0916/57759.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。