時區¶
預設啟用時區支援。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 中,因此是每個瀏覽器的設定。
注意
如果您已將 Airflow 安裝設定為使用不同的預設時區,並希望 UI 使用相同的時區,請將 [webserver]
區段中的 default_ui_timezone
設定為空字串或相同的值。
(目前預設為 UTC,以保持 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)
Naive datetime 物件的解讀¶
雖然 Airflow 完全以時區感知方式運作,但它仍然接受 DAG 定義中 start_dates
和 end_dates
的 naive 日期時間物件。這主要是為了保持向後相容性。如果遇到 naive 的 start_date
或 end_date
,則會套用預設時區。套用的方式是假設 naive 日期時間已在預設時區中。換句話說,如果您將預設時區設定為 Europe/Amsterdam
並建立 naive 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
不幸的是,在 DST 轉換期間,某些日期時間不存在或不明確。在這種情況下,pendulum 會引發例外。這就是為什麼當啟用時區支援時,您應該始終建立 aware datetime 物件的原因。
實際上,這很少是問題。Airflow 在模型和 DAG 中為您提供時區感知 datetime 物件,而且大多數時候,新的 datetime 物件是透過 timedelta 算術從現有物件建立的。應用程式程式碼中經常建立的唯一 datetime 是目前時間,而 timezone.utcnow()
會自動執行正確的操作。
時區感知 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 在範本中傳回時區感知日期時間,但不會將它們轉換為當地時間,因此它們仍為 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 執行,而與日光節約時間無關。