時區¶
時區支援預設啟用。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 執行,無論是否夏令時。