首页/数据/SQL 速查/INTERVAL 运算的月底与语义细节
函数速查60 条

INTERVAL 运算的月底与语义细节

INTERVAL 的日期运算有隐含规则:加月遇到目标月天数不足会截到月末;'1 month' 与 '30 days' 并不等价。

SQL 速查数据更新于 2026-10-13

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'(带引号的字符串),把两者互相照搬都会报语法错误。
跨月、跨年、闰年、夏令时是日期运算的四个雷区,这些场景不要靠推理:直接在目标数据库版本上跑一遍具体日期验证,升级或迁移数据库前更要重新验证。

易错点

  • 用「加 30 天」近似「加一个月」,月末与 2 月场景算错账期
  • 按固定天数推算跨月日期,遇到 31 天月份与 2 月时结果与业务预期不符
  • 把 INTERVAL 当成固定时长:带时区的时间戳加一天在夏令时切换日不等于 24 小时
  • 在 PostgreSQL 里照抄 MySQL 的 `date + INTERVAL 1 DAY` 不带引号写法,语法报错

数据来源与参考

  • MySQL 8.0 Reference Manual · Date Arithmetic
  • PostgreSQL Documentation · Date/Time Functions and Operators
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌