时区¶
时区支持默认启用。Airflow 在内部和数据库中将日期时间信息存储为 UTC。它允许您使用依赖于时区的调度来运行您的 DAG。目前,Airflow 不会在用户界面中将其转换为最终用户的时区。它在那里总是以 UTC 显示。同样,操作符中使用的模板也不会转换。时区信息是公开的,由 DAG 的编写者决定如何处理它。
如果您的用户居住在多个时区,并且您希望根据每个用户的本地时间显示日期时间信息,这会非常方便。
即使您仅在一个时区运行 Airflow,将数据以 UTC 格式存储在数据库中仍然是最佳实践(在 Airflow 支持时区感知之前,这也一直是推荐甚至强制的设置)。主要原因是许多国家/地区使用夏令时 (DST),在春季将时钟向前拨,在秋季向后拨。如果您在本地时间工作,很可能会在转换发生时每年遇到两次错误。(pendulum 和 pytz 文档更详细地讨论了这些问题。)对于简单的 DAG 来说,这可能无关紧要,但如果您从事金融服务等行业,需要满足每日截止日期,这将是一个问题。
时区在 airflow.cfg
中设置。默认情况下设置为 UTC,但您可以更改它以使用系统的设置或任意 IANA 时区,例如 Europe/Amsterdam
。它依赖于 pendulum
,后者比 pytz
更准确。安装 Airflow 时会安装 Pendulum。
注意
Pendulum 默认依赖于其自己的时区数据库,该数据库的更新频率不如 IANA 数据库。您可以通过将 PYTZDATA_TZDATADIR
环境变量设置为系统的数据库路径(例如 /usr/share/zoneinfo
)来使 Pendulum 依赖于系统的数据库。
Web UI¶
默认情况下,Web UI 将以 UTC 显示时间。可以通过使用右上角的菜单(点击时钟激活)来更改显示的时区。

“本地”时区由浏览器时区检测。“服务器”值来自 [core]
部分中的 default_timezone
设置。
用户选择的时区存储在 LocalStorage 中,因此是按浏览器设置的。
注意
UI 默认使用系统时区。用户可以通过 UI 的时区选择器更改其时区偏好设置。
概念¶
朴素(naive)和感知(aware)的 datetime 对象¶
Python 的 datetime.datetime 对象有一个 tzinfo 属性,可用于存储时区信息,表示为 datetime.tzinfo 子类的实例。设置此属性并描述偏移量时,datetime 对象是感知的(aware)。否则,它是朴素的(naive)。
您可以使用 timezone.is_localized()
和 timezone.is_naive()
来确定 datetime 对象是感知(aware)还是朴素(naive)。
因为 Airflow 使用时区感知的 datetime 对象。如果您的代码创建 datetime 对象,它们也需要是感知的(aware)。
from airflow.utils import timezone
now = timezone.utcnow()
a_date = timezone.datetime(2017, 1, 1)
朴素 datetime 对象的解释¶
虽然 Airflow 完全以时区感知的方式运行,但为了保持向后兼容性,它仍然接受 DAG 定义中 start_dates
和 end_dates
的朴素日期时间对象。如果遇到朴素的 start_date
或 end_date
,将应用默认时区。应用方式是假设朴素日期时间已处于默认时区。换句话说,如果您的默认时区设置为 Europe/Amsterdam
并创建了朴素的 datetime start_date
对象 datetime(2017, 1, 1)
,则假定这是 2017 年 1 月 1 日阿姆斯特丹时间的 start_date
。
dag = DAG(
"my_dag",
start_date=pendulum.datetime(2017, 1, 1, tz="UTC"),
default_args={"retries": 3},
)
op = BashOperator(task_id="hello_world", bash_command="Hello World!", dag=dag)
print(op.retries) # 3
不幸的是,在夏令时转换期间,某些日期时间可能不存在或存在歧义。在这种情况下,pendulum 会引发异常。因此,启用时区支持后,您应始终创建感知的 datetime 对象。
实际上,这很少成为问题。Airflow 在模型和 DAG 中提供时区感知的 datetime 对象,而且通常情况下,新的 datetime 对象是通过 timedelta 算术从现有对象创建的。应用代码中唯一经常创建的 datetime 对象是当前时间,而 timezone.utcnow()
会自动正确处理。
默认时区¶
默认时区是由 [core]
部分下的 default_timezone
设置定义的时区。如果您刚安装 Airflow,它将设置为 utc
,这是推荐的设置。您也可以将其设置为 system
或 IANA 时区(例如 Europe/Amsterdam
)。DAG 也在 Airflow worker 上评估,因此确保所有 Airflow 节点上的此设置一致非常重要。
[core]
default_timezone = utc
注意
有关设置配置的更多信息,请参阅设置配置选项
时区感知的 DAG¶
创建时区感知的 DAG 非常简单。只需确保使用 pendulum
提供时区感知的 start_date
。不要尝试使用标准库的 timezone 对象,因为它们已知存在限制,我们特意不允许在 DAG 中使用它们。
import pendulum
dag = DAG("my_tz_dag", start_date=pendulum.datetime(2016, 1, 1, tz="Europe/Amsterdam"))
op = EmptyOperator(task_id="empty", dag=dag)
print(dag.timezone) # <Timezone [Europe/Amsterdam]>
请注意,虽然可以为任务设置 start_date
和 end_date
,但始终会使用 DAG 时区或全局时区(按此顺序)来计算数据间隔。首次遇到时,开始日期或结束日期将使用与 start_date
或 end_date
相关联的时区转换为 UTC,然后在此基础上进行计算,时区信息将被忽略。
注意
编写时区感知的 DAG 时,必须确保底层时区库(例如:pendulum)已更新,包含了最新的法规变更(夏令时变更等)。预计时间发生变化时,您应与底层时区库确认转换是否会按预期发生。可能需要更新库版本。一般建议是,如果可能,最好以 UTC 编写 DAG。
模板¶
Airflow 在模板中返回时区感知的 datetime 对象,但不会将它们转换为本地时间,因此它们仍保持 UTC。这由 DAG 自行处理。
import pendulum
local_tz = pendulum.timezone("Europe/Amsterdam")
local_tz.convert(logical_date)
Cron 调度¶
使用 Cron 调度的时区感知的 DAG 会遵守夏令时。例如,一个开始日期为 US/Eastern
时区且调度为 0 0 * * *
的 DAG 在夏令时期间将每天在 UTC 04:00 运行,否则在 05:00 运行。
时间差¶
使用 timedelta
或 relativedelta
调度的时区感知的 DAG 会遵守开始日期的夏令时,但在调度后续运行时不会调整夏令时。例如,一个开始日期为 pendulum.datetime(2020, 1, 1, tz="UTC")
且调度间隔为 timedelta(days=1)
的 DAG 将每天在 UTC 05:00 运行,无论是否夏令时。