三个层次的时区问题
调度时区决定 cron 表达式按哪个时区解释。常见故障都来自三层时区不一致:调度系统自身按 UTC 运行,DAG 或任务的时区设置决定 schedule 的解释基准,数据存储侧(数据库、数仓)又可能用另一套约定。三层不一致时的典型现象是任务整体偏移若干小时,或者报表里「某天的数据少了几个小时」。
基本信息
| 三层时区 | 调度系统时区、DAG 与任务时区、数据存储时区 |
|---|---|
| Airflow 要求 | start_date 必须是 timezone-aware,建议显式指定 |
| 核对方法 | 看 DAG 详情页显示的 Next Run 时间是否符合预期 |
| 常见坑 | 服务器用 UTC、报表按北京时间解读,差 8 小时 |
典型使用场景
- 跨国团队协作:统一以 UTC 存储,按使用方时区展示
- 日切任务:明确业务日期按哪个时区界定,避免跨天歧义
- 夏令时地区:美国、欧洲部分地区的时钟跳变要专门验证
- 调度器迁移:从本地时区迁到 UTC 时,历史 cron 语义需要复核
- 排查数据缺失:先确认是时区偏移还是任务确实没跑
Airflow 指定本地时区
Airflow 指定本地时区
import pendulum
from airflow import DAG
local_tz = pendulum.timezone('Asia/Shanghai')
dag = DAG(
'daily_orders',
start_date=pendulum.datetime(2026, 1, 1, tz=local_tz), # 明确时区,避免按默认解释
schedule='0 2 * * *', # 按 Asia/Shanghai 解释为凌晨 2 点
catchup=False,
)
# 若调度器运行在 UTC,未指定时区的 start_date 会被当作 UTC,执行时间整体偏移时区层级与影响
| 层级 | 典型取值 | 不一致的表现 |
|---|---|---|
| 调度系统 | UTC 或本地时区 | DAG 整体偏移若干小时 |
| DAG 与任务 | Asia/Shanghai 等 | cron 解释基准与预期不符 |
| 数据存储 | 多为 UTC | 报表按本地时间查询时少一段数据 |
| 业务日期定义 | 按本地自然日 | 跨天任务的归属日期出现分歧 |
服务器与数据库统一用 UTC、而报表按北京时间解读时,查数必须统一转换口径,否则会出现「同一天数据少 8 小时」这类看起来像丢数的问题。
夏令时切换地区在跳变当天可能出现任务被跳过或重复执行,涉及这些地区的调度必须单独验证,不能假设 cron 语义与时区无关。