首页/数据/数据工程与 ETL 速查/业务日期与运行时间

业务日期与运行时间

业务日期(数据属于哪一天)与运行时间(任务实际几点跑)是两个概念:日批通常运行在 T+1,处理的是 T 日数据;补数时尤其要区分,否则会错位覆盖。

两个容易混淆的日期

业务日期(bizdate)指数据归属哪一天;运行时间指任务实际在几点执行。日批任务通常运行在 T+1 的凌晨,处理的是 T 这一天的数据,两者永远差一天。调度平台通过参数把业务日期注入任务,任务内部不再自己算日期。

为什么必须区分

补数是暴露问题最集中的场景:任务里写「当前日期减一天」的写法,在补跑一个月前的数据时会去读昨天的分区,要么读不到数据、要么写到错误的分区覆盖了别的日期。用调度参数注入业务日期,补数时只需改参数,不用改代码。

两种日期对照

概念含义示例
业务日期(bizdate)数据归属的日期2026-10-11 的数据
运行时间任务实际触发的时刻2026-10-12 凌晨 02:00
数据区间本次任务处理的时间范围[2026-10-11 00:00, 2026-10-12 00:00)
参数注入由调度平台传入,任务不自己计算${bizdate} 或 {{ ds }}

基本信息

业务日期数据归属日期,日批通常为昨天
运行时间调度实际触发的时刻
传递方式调度参数(如 ${bizdate}、{{ ds }})注入 SQL
补数影响参数化后改参数即可回填历史,不需要改代码
跨天任务需要明确约定归属哪一天,并在链路上保持一致

典型使用场景

  • 日批读取:按业务日期读取当天分区,写入对应日期的结果分区
  • 补数:把业务日期设为历史某天,重跑当天的链路
  • 跨天任务:23:50 开始、次日 00:20 结束的任务,明确归属哪一天
  • 多时区业务:统一以某个时区确定业务日期边界
  • 对账核对:确认上下游任务使用的是同一个业务日期口径

参数传递示例

参数传递示例
-- 每天 02:00 执行的 SQL:dt 取业务日期,而不是运行日期
SELECT * FROM ods_orders
WHERE dt = '${bizdate}';      -- 例如 2026-10-11,实际运行在 10-12 凌晨

-- 写入时同样使用业务日期,保证分区与数据归属一致
INSERT OVERWRITE TABLE dwd_order_di PARTITION (dt = '${bizdate}')
SELECT order_id, amount FROM ods_orders WHERE dt = '${bizdate}';

调度平台参数差异

调度平台参数差异
# 不同平台的内置参数名称不同,迁移时需要逐条核对
# 常见形式:
#   ${bizdate}、${yyyymmdd}        部分平台的业务日期参数
#   {{ ds }}                       Airflow:数据区间开始日期(周期内)
#   ${system.biz.date}             DolphinScheduler:业务日期

# 通用原则:任务里只引用平台参数,绝不写“当前日期减一天”
Airflow 的周期语义是把「运行时间」放在数据区间结束之后:一个标记为 10 月 12 日运行的日任务,处理的是 10 月 11 日的数据区间。理解这一点,才不会把两条链路的日期参数对齐错。
时区不一致会让业务日期整体偏移一天:本地时间与 UTC 混用时,边界时刻的任务可能算到相邻日期,写入错误分区并覆盖已有数据。

易错点

  • 在 SQL 里写死「当前日期减一天」,补数历史日期时读错分区,甚至覆盖其它日期的数据
  • 跨天任务不约定归属日,上下游分别按不同口径处理,对账时出现整天的差异
  • 平台时区与业务时区不一致,边界任务写入相邻日期分区,覆盖已有数据
  • 上下游任务使用不同的日期参数(一个用业务日期、一个用运行日期),链路数字整体错位一天

数据来源与参考

  • Apache Airflow 官方文档:Data Interval 与 Templates
  • Apache DolphinScheduler 官方文档:内置参数
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌