You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Airflow伦敦时区夏令时调度异常问题排查与解决

夏令时切换下Airflow DAG调度问题解决方案

用户问题场景

用户的Airflow DAG代码如下:

from airflow import DAG
import pendulum

with DAG(
    dag_id="DLS_DAG",
    start_date = pendulum.datetime(2023, 10, 20, 5, tz="Europe/London"),
    schedule = '15,45 1 * * *',
    catchup=False,
    tags=["daylight_saving_testing"],
    )

该DAG原定每天伦敦时间1:15和1:45运行。2023年10月29日夏令时结束(时钟回拨1小时,出现两个1:00-2:00时段),任务触发了首次1:15、1:45的运行,还触发了重复时段的1:45运行,但跳过了重复时段的1:15运行。需求是跳过重复时段的两次运行,且必须使用伦敦时区,无法切换为UTC。


一、为何仅跳过重复时段的一次运行?

Airflow底层基于UTC时间计算调度间隔,所有本地时间都会转换为UTC进行跟踪。2023年10月29日伦敦夏令时结束时:

  • 第一次1:15(BST,UTC+1)→ UTC 00:15
  • 第一次1:45(BST,UTC+1)→ UTC 00:45
  • 回拨后的1:15(GMT,UTC+0)→ UTC 01:15
  • 回拨后的1:45(GMT,UTC+0)→ UTC 01:45

Airflow的调度逻辑会对比上一次运行的UTC时间,生成下一个符合cron规则的UTC时间。回拨后的1:15对应UTC 01:15,这个时间点落在前一次调度(UTC 00:45)到下一个预期调度(UTC 01:45)的间隔内,Airflow会判定该时间点属于“重复逻辑周期”,认为已处理过,所以跳过;而回拨后的1:45对应UTC 01:45,是下一个明确的UTC间隔点,因此被触发。


二、如何跳过重复时段的两次运行?

要完全跳过夏令时回拨的重复时段运行,最可靠的方式是自定义Timetable,在生成调度时间时过滤掉重复时段的时间点。以下是实现代码:

1. 定义夏令时安全的Timetable类

from airflow.timetables.base import DagRunInfo
from airflow.timetables.interval import CronTimetable
from pendulum import DateTime, timezone

LONDON_TZ = timezone("Europe/London")

class DSTSafeCronTimetable(CronTimetable):
    def next_dagrun_info(
        self,
        last_automated_dagrun: DateTime | None,
        restriction: DateTime | None,
    ) -> DagRunInfo | None:
        # 先调用父类获取默认下一个调度时间
        dagrun_info = super().next_dagrun_info(last_automated_dagrun, restriction)
        if not dagrun_info:
            return None
        
        scheduled_local_time = dagrun_info.data_interval.start.in_timezone(LONDON_TZ)
        # 通用判断:识别夏令时回拨的重复时段
        # 回拨后的时段特征:当前本地时间的DST为False,加1小时后DST为True
        one_hour_later = scheduled_local_time.add(hours=1)
        if scheduled_local_time.is_dst() is False and one_hour_later.is_dst() is True:
            # 跳过重复时段,递归获取下一个有效调度时间
            return self.next_dagrun_info(scheduled_local_time, restriction)
        return dagrun_info

2. 在DAG中使用自定义Timetable

from airflow import DAG
import pendulum

with DAG(
    dag_id="DLS_DAG",
    start_date = pendulum.datetime(2023, 10, 20, 5, tz="Europe/London"),
    # 替换原schedule参数为自定义Timetable
    timetable=DSTSafeCronTimetable("15,45 1 * * *", timezone="Europe/London"),
    catchup=False,
    tags=["daylight_saving_testing"],
) as dag:
    # 此处添加你的任务定义
    pass

这个Timetable会自动识别夏令时回拨的重复时段,跳过该时段内的所有调度点,完全符合需求。


三、三月夏令时调整时的任务触发情况

三月夏令时开始时,伦敦时间会从1:00直接跳至2:00,1:00-2:00的本地时段完全不存在。此时Airflow不会触发该时段的任务,因为这些本地时间无法转换为有效的UTC时间(时区转换会出现时间断裂),Airflow会直接跳过缺失的时段,调度下一个存在的有效时间点。


内容的提问来源于stack exchange,提问作者santanu basu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:14:52