CURDATE / CURTIME 是什么
CURDATE() 返回当前日期,CURTIME() 返回当前时间(不含日期),NOW() / CURRENT_TIMESTAMP 返回完整的日期时间。三者都取会话时区下的当前时刻:MySQL 看 time_zone 参数,PostgreSQL 看 timezone 参数。把日期与时间分开取的价值在于按天分组与按天过滤:用 CURDATE() 配合范围条件比先取 NOW() 再截断更直接,也能避免日期函数套在列上导致索引失效。
基本信息
| MySQL 写法 | CURDATE() / CURRENT_DATE、CURTIME() / CURRENT_TIME、NOW() / CURRENT_TIMESTAMP |
|---|---|
| PostgreSQL 写法 | CURRENT_DATE、CURRENT_TIME、now() / CURRENT_TIMESTAMP |
| 时区 | 取决于会话时区参数,应用连接与库时区不一致时结果可能差一天 |
| 返回值类型 | 日期为 DATE,时间为 TIME,完整值为 DATETIME / TIMESTAMP |
| 一致性 | 同一语句内 NOW() 取值固定(MySQL 取语句开始时刻,PG 取事务开始时刻) |
典型使用场景
- 今天的数据统计:按天做范围过滤
- 生成当天的分区名、表名或文件路径
- 计算账期、宽限期与年龄
- 展示「距今天数」等业务指标
- 定时任务判断是否已跨天,决定是否触发日切逻辑
MySQL 用法
MySQL 用法
SELECT CURDATE() AS d, # 2026-10-13
CURTIME() AS t, # 14:05:33
NOW() AS ts; # 2026-10-13 14:05:33
# 查今天的数据:用范围条件,避免在列上套函数
SELECT COUNT(*) FROM orders
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
# 反例:列上套函数,索引失效
SELECT COUNT(*) FROM orders WHERE DATE(created_at) = CURDATE();PostgreSQL 用法
PostgreSQL 用法
SELECT CURRENT_DATE AS d, CURRENT_TIME AS t, now() AS ts;
SELECT count(*) FROM orders
WHERE created_at >= CURRENT_DATE
AND created_at < CURRENT_DATE + INTERVAL '1 day';
-- 确认会话时区,避免与预期差一天
SELECT now() AS with_tz, CURRENT_DATE AS today, current_setting('TimeZone') AS tz;返回值与用途
| 写法 | 返回值 | 典型用途 |
|---|---|---|
| CURDATE() / CURRENT_DATE | 日期 | 按天过滤、当天的表名或分区名 |
| CURTIME() / CURRENT_TIME | 时间 | 只关心时刻、运行时段判断 |
| NOW() / now() | 日期时间 | 时间戳记录、计算间隔 |
| CURRENT_TIMESTAMP | 日期时间(标准写法) | 跨库通用,语义更明确 |
同一语句内 NOW() 与 CURRENT_TIMESTAMP 取值固定,所以重复调用结果一致;MySQL 的 SYSDATE() 返回函数真正执行的瞬间,属于特例,业务代码不应依赖这种差异。
CURDATE() 与日期时间列比较时按当天零点展开:MySQL 的 DATE 与 DATETIME 比较会自动补齐零点,PostgreSQL 里 CURRENT_DATE 与 timestamp 比较同样如此,所以用 >= 下界配合 < 次日上界是最稳的写法。
用 DATE(created_at) = CURDATE() 过滤当天数据会让 created_at 上的索引失效;改用范围比较(大于等于今天零点、小于明天零点),大表日志统计的差别非常明显。
需要「相差多少天」时不要拿两个日期直接做减法再截断:MySQL 用 DATEDIFF(结束, 开始),PostgreSQL 里 date 减 date 直接得到整数天数,都是一步到位的写法。