INTERVAL 日期运算是什么
INTERVAL 表示时间间隔,用于日期加减:MySQL 写 date + INTERVAL 1 DAY 或 DATE_ADD(date, INTERVAL 1 MONTH),PostgreSQL 写 date + INTERVAL '1 month' 这样的标准字符串。坑集中在「月」与「年」:加一个月不是加固定天数,2026-01-31 加一个月,MySQL 与 PostgreSQL 都会规整到目标月的最后一天(2026-02-28)。另一个细节是夏令时:带时区的时间戳加 INTERVAL '1 day' 在切换日不等于加 24 小时。跨月、闰年这类结果要用具体日期实测,别靠推理。
基本信息
| MySQL 语法 | date + INTERVAL n DAY、DATE_ADD(date, INTERVAL n MONTH)、DATE_SUB(...) |
|---|---|
| PostgreSQL 语法 | date + INTERVAL '1 day'、date - INTERVAL '1 month' |
| 单位写法 | MySQL 用 n 加单位关键字(可组合 DAY_HOUR 等);PG 用标准 SQL 字符串 |
| 返回类型 | MySQL 给 DATE 加纯日期单位仍返回 DATE,加含时间单位的间隔返回 DATETIME |
| 月末规则 | 目标月天数不足时规整到该月最后一天,两库行为一致 |
典型使用场景
- 算到期日与宽限期:今天加 30 天、加 7 个工作日
- 算上月同期,做环比对比
- 算账期与订阅周期,涉及月末与闰年要格外小心
- 生成连续日期序列,补全报表里缺失的日期
- 算 SLA 剩余时间与超期时长
MySQL 写法
MySQL 写法
SELECT CURDATE() + INTERVAL 30 DAY AS due_date, # 到期日
CURDATE() - INTERVAL 1 MONTH AS last_month, # 上月同期
DATE_ADD('2026-01-31', INTERVAL 1 MONTH) AS clip_demo, # 2026-02-28,按月末规整
NOW() + INTERVAL 2 HOUR AS deadline, # 含时间单位,返回 DATETIME
DATE_SUB(NOW(), INTERVAL 7 DAY) AS week_ago;PostgreSQL 写法
PostgreSQL 写法
SELECT CURRENT_DATE + INTERVAL '30 days' AS due_date,
CURRENT_DATE - INTERVAL '1 month' AS last_month,
'2026-01-31'::date + INTERVAL '1 month' AS clip_demo, -- 2026-02-28
now() + INTERVAL '2 hours' AS deadline;
-- 生成连续日期序列,用于补全缺失日期的报表
SELECT gs::date AS d
FROM generate_series(CURRENT_DATE - INTERVAL '6 days', CURRENT_DATE, INTERVAL '1 day') AS gs;常见写法与结果
| 表达式 | 结果 | 说明 |
|---|---|---|
| date + INTERVAL 1 DAY | 次日 | 纯日期单位,结果仍是日期 |
| date + INTERVAL 1 MONTH | 同日下月,超月末则规整 | 1 月 31 日得到 2 月末 |
| ts + INTERVAL 1 HOUR | 加一小时 | 保留时间部分 |
| timestamptz + INTERVAL '1 day' | 次日同一墙钟时刻 | 夏令时切换日不等于加 24 小时 |
涉及账单周期、订阅到期这类业务时,先明确月末与闰年的规整规则并对具体日期写测试用例;纯天数差用 DATEDIFF 或日期相减更直观,不要绕回 INTERVAL 运算。
单位写法两库不通用:MySQL 写 INTERVAL 1 DAY(数字加单位关键字),PostgreSQL 写 INTERVAL '1 day'(带引号的字符串),把两者互相照搬都会报语法错误。
跨月、跨年、闰年、夏令时是日期运算的四个雷区,这些场景不要靠推理:直接在目标数据库版本上跑一遍具体日期验证,升级或迁移数据库前更要重新验证。