首页/数据/NoSQL 速查/日期时间函数与时间对齐
ClickHouse56 条

日期时间函数与时间对齐

常用日期函数把时间戳归一到桶:toStartOfHour/Day/Month、toStartOfInterval 自定义区间对齐,dateDiff 计算差值,date_trunc 进行通用截断。

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

日期函数解决的两件事

ClickHouse 的日期时间函数主要做两件事:把时间戳归一到桶(toStartOfHour、toStartOfDay、toStartOfInterval、date_trunc),以及做时间运算(dateDiff、date_add、直接与 INTERVAL 相加)。聚合类报表几乎每条语句都会用到其中至少一类。

口径与时区怎么定

时间列最好统一按 UTC 或固定时区存储,展示层再换算,函数 toTimeZone 可以做时区切换。周起点这类容易随版本与设置变化的口径,应该用 toStartOfInterval 显式指定。另一个常见误区是在过滤前对时间列做时区换算,这样会丢掉分区裁剪能力。

基本信息

取整toStartOfMinute/Hour/Day/Week/Month/Quarter/Year
自定义区间toStartOfInterval(ts, INTERVAL 5 MINUTE) 或 date_trunc('minute', ts)
运算now()、today()、dateDiff('day', a, b)、ts + INTERVAL 1 DAY
时区toTimeZone(ts, 'Asia/Shanghai')
适用版本各主流版本均支持,个别函数为较新版本引入

示例

示例
SELECT
    toStartOfInterval(ts, INTERVAL 5 MINUTE) AS bucket,
    count() AS cnt
FROM metrics
WHERE ts >= now() - INTERVAL 1 HOUR
GROUP BY bucket
ORDER BY bucket;

-- 日期差值:注册到首次下单的间隔天数
SELECT dateDiff('day', reg_date, first_order_date) AS days_to_order
FROM users LIMIT 5;

-- 时区换算放展示层,过滤仍用原列
SELECT toTimeZone(ts, 'Asia/Shanghai') AS local_ts
FROM metrics LIMIT 5;

典型使用场景

  • 监控报表:按分钟或小时对齐时间轴做计数与均值
  • 用户行为:计算注册到首单、下单到支付的时间差
  • 分区路由:用日期函数生成分区键表达式
  • 同比环比:把时间列归一成天或月再自关联
  • 跨时区展示:存储用 UTC,报表按需换算

场景与推荐写法

场景推荐写法说明
固定粒度toStartOfHour/Day/Month语义明确,便于走分区与排序键
自定义粒度toStartOfInterval(ts, INTERVAL n UNIT)粒度与起点都能显式控制
通用截断date_trunc('minute', ts)与部分 SQL 方言习惯一致
求差值dateDiff('day', a, b)单位是字符串参数,拼写要准确
时区换算toTimeZone(ts, 'Zone')放在展示层,别放进过滤条件
时间列统一用 UTC 或固定时区存储、展示层再转换,是避免跨时区口径错乱最简单的方式;过滤条件尽量直接作用在原时区的时间列上。
toStartOfWeek 的周起点可能随版本与设置变化,关键口径要用 toStartOfInterval 显式指定,否则不同环境的报表会对不上;跨时区报表还要固定时间列本身的时区口径,避免同一份数据在不同客户端算出不同结果。

易错点

  • 对时间列做时区换算后再分组或过滤会损失分区裁剪能力,应尽量在原时区列上过滤
  • toStartOfWeek 的周起点在不同版本或设置下可能不同,跨环境报表要先对齐口径
  • dateDiff 的单位是字符串参数,写错单位不会报错但结果没有业务意义
  • 用 now() 与时间列比较时忽略存储时区,会让整个过滤区间偏移

数据来源与参考

  • ClickHouse Docs: Date and time functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌