日期加减是什么
日期加减是报表与定时任务的常用操作。MySQL 用 DATE_ADD(d, INTERVAL n UNIT),也可简写为 d + INTERVAL n UNIT 或 d - INTERVAL n UNIT,需要减时还能用 DATE_SUB;PostgreSQL 用 d + INTERVAL 'n unit'。两库的单位名称基本一致:DAY、WEEK、MONTH、YEAR、HOUR、MINUTE、SECOND。跨月与跨年计算要当心边界:月末加一个月可能落到下个月最后一天,报表口径要提前约定。
基本信息
| MySQL 加减 | DATE_ADD(d, INTERVAL 7 DAY) 与 DATE_SUB(d, INTERVAL 1 MONTH) |
|---|---|
| MySQL 简写 | d + INTERVAL 7 DAY 与 d - INTERVAL 1 MONTH |
| PostgreSQL | d + INTERVAL '7 day' 与 d - INTERVAL '1 month' |
| 常用单位 | DAY、WEEK、MONTH、YEAR、HOUR、MINUTE、SECOND |
| 类型变化 | PostgreSQL 中 date 加 interval 得到 timestamp |
| 边界情况 | 月末加月份可能落到下月最后一天,跨年同理 |
典型使用场景
- 报表时间窗口:算近 7 天、近 30 天的区间端点
- 定时任务:下次执行时间等于当前时间加一天
- 账期计算:账单日加一个月得到下期账单日
- 有效期判断:过期时间等于创建时间加有效期
- 数据清理:删除早于 90 天前的记录
- 周维度统计:用加减把日期对齐到本周一
示例
示例
-- MySQL
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY); # 七天后的同一时刻
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH); # 一个月前
SELECT NOW() + INTERVAL 30 MINUTE; # 简写形式
-- PostgreSQL
SELECT now() + INTERVAL '7 day';
SELECT now() - INTERVAL '1 month';
SELECT now() + INTERVAL '2 hours 30 minutes';
-- 区间查询:半开区间避免漏边界
SELECT * FROM orders
WHERE created_at >= '2024-05-01' AND created_at < '2024-06-01';写法对照
| 需求 | MySQL | PostgreSQL |
|---|---|---|
| 加 7 天 | DATE_ADD(d, INTERVAL 7 DAY) | d + INTERVAL '7 day' |
| 减 1 个月 | DATE_SUB(d, INTERVAL 1 MONTH) | d - INTERVAL '1 month' |
| 加 2 小时 | d + INTERVAL 2 HOUR | d + INTERVAL '2 hours' |
| 日期差 | DATEDIFF(d1, d2) | d1 - d2 得到天数 |
| 取月份首日 | DATE_FORMAT(d, '%Y-%m-01') | date_trunc('month', d) |
区间查询用半开区间最稳:created_at >= 起点 AND created_at < 终点,避免终点当天有 23 小时被漏掉。
给时间列加常量做运算会让索引失效,写成 whereEnd 常量比较才对:把 NOW() - INTERVAL 7 DAY 放在条件右侧不影响左侧列的索引使用。
按月加减在月末有歧义:1 月 31 日加一个月在不同数据库上的结果不完全一致,涉及账期的计算要显式约定取月末还是下月同日。
把常用的时间窗口封装成公共函数或视图:近七天、近三十天这类区间在多处复用,集中定义能避免每处各写一套、边界各不相同。
报表里的时间窗口尽量统一用半开区间表达,并把时区与口径写进接口文档,跨团队协作时能省下大量对齐成本。