Skip to content

Commit 969a275

Browse files
potiukjedcunningham
authored andcommitted
Clarify pendulum use in timezone cases (#21646)
It is important to use Pendulum in case timezone is used - because there are a number of limitations coming from using stdlib timezone implementation. However our documentation was not very clear about it, especially some examples shown using standard datetime in DAGs which could mislead our users to continue using datetime if they use timezone. This PR clarifies and stresses the use of pendulum is necessary when timezone is used. Also it points to the documentation in case serialization throws error about not using Pendulum so that the users can learn about the reasoning. This is the first part of the change - the follow up will be changing all provider examples to also use timezone and pendulum explicitly. See also #20070 (cherry picked from commit f011da2)
1 parent 56d82fc commit 969a275

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+216
-120
lines changed

CONTRIBUTING.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ We are using certain prefixes for email subjects for different purposes. Start y
13761376
Voting is governed by the rules described in `Voting <https://www.apache.org/foundation/voting.html>`_
13771377

13781378
We are all devoting our time for community as individuals who except for being active in Apache Airflow have
1379-
families, daily jobs, right for vacation. Sometimes we are in different time zones or simply are
1379+
families, daily jobs, right for vacation. Sometimes we are in different timezones or simply are
13801380
busy with day-to-day duties that our response time might be delayed. For us it's crucial
13811381
to remember to respect each other in the project with no formal structure.
13821382
There are no managers, departments, most of us is autonomous in our opinions, decisions.

UPDATING.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ Similarly, `DAG.concurrency` has been renamed to `DAG.max_active_tasks`.
184184
```python
185185
dag = DAG(
186186
dag_id="example_dag",
187-
start_date=datetime(2021, 1, 1),
187+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
188188
catchup=False,
189189
concurrency=3,
190190
)
@@ -195,7 +195,7 @@ dag = DAG(
195195
```python
196196
dag = DAG(
197197
dag_id="example_dag",
198-
start_date=datetime(2021, 1, 1),
198+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
199199
catchup=False,
200200
max_active_tasks=3,
201201
)
@@ -3216,7 +3216,7 @@ Type "help", "copyright", "credits" or "license" for more information.
32163216
>>> from airflow.models.dag import DAG
32173217
>>> from airflow.operators.dummy import DummyOperator
32183218
>>>
3219-
>>> dag = DAG('simple_dag', start_date=datetime(2017, 9, 1))
3219+
>>> dag = DAG('simple_dag', start_date=pendulum.datetime(2017, 9, 1, tz="UTC"))
32203220
>>>
32213221
>>> task = DummyOperator(task_id='task_1', dag=dag)
32223222
>>>

airflow/example_dags/example_bash_operator.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
"""Example DAG demonstrating the usage of the BashOperator."""
2020

21-
from datetime import datetime, timedelta
21+
import datetime
22+
23+
import pendulum
2224

2325
from airflow import DAG
2426
from airflow.operators.bash import BashOperator
@@ -27,9 +29,9 @@
2729
with DAG(
2830
dag_id='example_bash_operator',
2931
schedule_interval='0 0 * * *',
30-
start_date=datetime(2021, 1, 1),
32+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3133
catchup=False,
32-
dagrun_timeout=timedelta(minutes=60),
34+
dagrun_timeout=datetime.timedelta(minutes=60),
3335
tags=['example', 'example2'],
3436
params={"example_key": "example_value"},
3537
) as dag:

airflow/example_dags/example_branch_datetime_operator.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
Example DAG demonstrating the usage of DateTimeBranchOperator with datetime as well as time objects as
2121
targets.
2222
"""
23-
import datetime
23+
import pendulum
2424

2525
from airflow import DAG
2626
from airflow.operators.datetime import BranchDateTimeOperator
2727
from airflow.operators.dummy import DummyOperator
2828

2929
dag = DAG(
3030
dag_id="example_branch_datetime_operator",
31-
start_date=datetime.datetime(2021, 1, 1),
31+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3232
catchup=False,
3333
tags=["example"],
3434
schedule_interval="@daily",
@@ -42,8 +42,8 @@
4242
task_id='datetime_branch',
4343
follow_task_ids_if_true=['date_in_range'],
4444
follow_task_ids_if_false=['date_outside_range'],
45-
target_upper=datetime.datetime(2020, 10, 10, 15, 0, 0),
46-
target_lower=datetime.datetime(2020, 10, 10, 14, 0, 0),
45+
target_upper=pendulum.datetime(2020, 10, 10, 15, 0, 0),
46+
target_lower=pendulum.datetime(2020, 10, 10, 14, 0, 0),
4747
dag=dag,
4848
)
4949

@@ -54,7 +54,7 @@
5454

5555
dag = DAG(
5656
dag_id="example_branch_datetime_operator_2",
57-
start_date=datetime.datetime(2021, 1, 1),
57+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
5858
catchup=False,
5959
tags=["example"],
6060
schedule_interval="@daily",
@@ -67,8 +67,8 @@
6767
task_id='datetime_branch',
6868
follow_task_ids_if_true=['date_in_range'],
6969
follow_task_ids_if_false=['date_outside_range'],
70-
target_upper=datetime.time(0, 0, 0),
71-
target_lower=datetime.time(15, 0, 0),
70+
target_upper=pendulum.time(0, 0, 0),
71+
target_lower=pendulum.time(15, 0, 0),
7272
dag=dag,
7373
)
7474

airflow/example_dags/example_branch_day_of_week_operator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
"""
2020
Example DAG demonstrating the usage of BranchDayOfWeekOperator.
2121
"""
22-
from datetime import datetime
22+
import pendulum
2323

2424
from airflow import DAG
2525
from airflow.operators.dummy import DummyOperator
2626
from airflow.operators.weekday import BranchDayOfWeekOperator
2727

2828
with DAG(
2929
dag_id="example_weekday_branch_operator",
30-
start_date=datetime(2021, 1, 1),
30+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3131
catchup=False,
3232
tags=["example"],
3333
schedule_interval="@daily",

airflow/example_dags/example_branch_labels.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
"""
2020
Example DAG demonstrating the usage of labels with different branches.
2121
"""
22-
from datetime import datetime
22+
import pendulum
2323

2424
from airflow import DAG
2525
from airflow.operators.dummy import DummyOperator
2626
from airflow.utils.edgemodifier import Label
2727

2828
with DAG(
29-
"example_branch_labels", schedule_interval="@daily", start_date=datetime(2021, 1, 1), catchup=False
29+
"example_branch_labels",
30+
schedule_interval="@daily",
31+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
32+
catchup=False,
3033
) as dag:
3134
ingest = DummyOperator(task_id="ingest")
3235
analyse = DummyOperator(task_id="analyze")

airflow/example_dags/example_branch_operator.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"""Example DAG demonstrating the usage of the BranchPythonOperator."""
2020

2121
import random
22-
from datetime import datetime
22+
23+
import pendulum
2324

2425
from airflow import DAG
2526
from airflow.operators.dummy import DummyOperator
@@ -29,7 +30,7 @@
2930

3031
with DAG(
3132
dag_id='example_branch_operator',
32-
start_date=datetime(2021, 1, 1),
33+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3334
catchup=False,
3435
schedule_interval="@daily",
3536
tags=['example', 'example2'],

airflow/example_dags/example_branch_python_dop_operator_3.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
Example DAG demonstrating the usage of BranchPythonOperator with depends_on_past=True, where tasks may be run
2121
or skipped on alternating runs.
2222
"""
23-
from datetime import datetime
23+
import pendulum
2424

2525
from airflow import DAG
2626
from airflow.operators.dummy import DummyOperator
@@ -49,7 +49,7 @@ def should_run(**kwargs):
4949
with DAG(
5050
dag_id='example_branch_dop_operator_v3',
5151
schedule_interval='*/1 * * * *',
52-
start_date=datetime(2021, 1, 1),
52+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
5353
catchup=False,
5454
default_args={'depends_on_past': True},
5555
tags=['example'],

airflow/example_dags/example_complex.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"""
2020
Example Airflow DAG that shows the complex DAG structure.
2121
"""
22-
from datetime import datetime
22+
import pendulum
2323

2424
from airflow import models
2525
from airflow.models.baseoperator import chain
@@ -28,7 +28,7 @@
2828
with models.DAG(
2929
dag_id="example_complex",
3030
schedule_interval=None,
31-
start_date=datetime(2021, 1, 1),
31+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3232
catchup=False,
3333
tags=['example', 'example2', 'example3'],
3434
) as dag:

airflow/example_dags/example_dag_decorator.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
# KIND, either express or implied. See the License for the
1616
# specific language governing permissions and limitations
1717
# under the License.
18-
from datetime import datetime
1918
from typing import Any, Dict
2019

2120
import httpx
21+
import pendulum
2222

2323
from airflow.decorators import dag, task
2424
from airflow.models.baseoperator import BaseOperator
@@ -37,7 +37,12 @@ def execute(self, context):
3737

3838

3939
# [START dag_decorator_usage]
40-
@dag(schedule_interval=None, start_date=datetime(2021, 1, 1), catchup=False, tags=['example'])
40+
@dag(
41+
schedule_interval=None,
42+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
43+
catchup=False,
44+
tags=['example'],
45+
)
4146
def example_dag_decorator(email: str = 'example@example.com'):
4247
"""
4348
DAG to send server IP to email.

airflow/example_dags/example_external_task_marker_dag.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@
3737
exception
3838
"""
3939

40-
import datetime
40+
import pendulum
4141

4242
from airflow import DAG
4343
from airflow.operators.dummy import DummyOperator
4444
from airflow.sensors.external_task import ExternalTaskMarker, ExternalTaskSensor
4545

46-
start_date = datetime.datetime(2015, 1, 1)
46+
start_date = pendulum.datetime(2021, 1, 1, tz="UTC")
4747

4848
with DAG(
4949
dag_id="example_external_task_marker_parent",

airflow/example_dags/example_kubernetes_executor.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"""
2121
import logging
2222
import os
23-
from datetime import datetime
23+
24+
import pendulum
2425

2526
from airflow import DAG
2627
from airflow.configuration import conf
@@ -45,7 +46,7 @@
4546
with DAG(
4647
dag_id='example_kubernetes_executor',
4748
schedule_interval=None,
48-
start_date=datetime(2021, 1, 1),
49+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
4950
catchup=False,
5051
tags=['example3'],
5152
) as dag:

airflow/example_dags/example_latest_only_with_trigger.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
"""
2121

2222
# [START example]
23-
import datetime as dt
23+
import datetime
24+
25+
import pendulum
2426

2527
from airflow import DAG
2628
from airflow.operators.dummy import DummyOperator
@@ -29,8 +31,8 @@
2931

3032
with DAG(
3133
dag_id='latest_only_with_trigger',
32-
schedule_interval=dt.timedelta(hours=4),
33-
start_date=dt.datetime(2021, 1, 1),
34+
schedule_interval=datetime.timedelta(hours=4),
35+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3436
catchup=False,
3537
tags=['example3'],
3638
) as dag:

airflow/example_dags/example_nested_branch_dag.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
``none_failed_min_one_success`` trigger rule such that they are skipped whenever their corresponding
2222
``BranchPythonOperator`` are skipped.
2323
"""
24-
from datetime import datetime
24+
import pendulum
2525

2626
from airflow.models import DAG
2727
from airflow.operators.dummy import DummyOperator
@@ -30,7 +30,7 @@
3030

3131
with DAG(
3232
dag_id="example_nested_branch_dag",
33-
start_date=datetime(2021, 1, 1),
33+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3434
catchup=False,
3535
schedule_interval="@daily",
3636
tags=["example"],

airflow/example_dags/example_passing_params_via_test_command.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818

1919
"""Example DAG demonstrating the usage of the params arguments in templated arguments."""
2020

21+
import datetime
2122
import os
22-
from datetime import datetime, timedelta
2323
from textwrap import dedent
2424

25+
import pendulum
26+
2527
from airflow import DAG
2628
from airflow.decorators import task
2729
from airflow.operators.bash import BashOperator
@@ -61,9 +63,9 @@ def print_env_vars(test_mode=None):
6163
with DAG(
6264
"example_passing_params_via_test_command",
6365
schedule_interval='*/1 * * * *',
64-
start_date=datetime(2021, 1, 1),
66+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
6567
catchup=False,
66-
dagrun_timeout=timedelta(minutes=4),
68+
dagrun_timeout=datetime.timedelta(minutes=4),
6769
tags=['example'],
6870
) as dag:
6971
run_this = my_py_command(params={"miff": "agg"})

airflow/example_dags/example_python_operator.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
import logging
2424
import shutil
2525
import time
26-
from datetime import datetime
2726
from pprint import pprint
2827

28+
import pendulum
29+
2930
from airflow import DAG
3031
from airflow.decorators import task
3132

@@ -34,7 +35,7 @@
3435
with DAG(
3536
dag_id='example_python_operator',
3637
schedule_interval=None,
37-
start_date=datetime(2021, 1, 1),
38+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3839
catchup=False,
3940
tags=['example'],
4041
) as dag:

airflow/example_dags/example_short_circuit_operator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# under the License.
1818

1919
"""Example DAG demonstrating the usage of the ShortCircuitOperator."""
20-
from datetime import datetime
20+
import pendulum
2121

2222
from airflow import DAG
2323
from airflow.models.baseoperator import chain
@@ -26,7 +26,7 @@
2626

2727
with DAG(
2828
dag_id='example_short_circuit_operator',
29-
start_date=datetime(2021, 1, 1),
29+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
3030
catchup=False,
3131
tags=['example'],
3232
) as dag:

airflow/example_dags/example_skip_dag.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
"""Example DAG demonstrating the DummyOperator and a custom DummySkipOperator which skips by default."""
2020

21-
from datetime import datetime
21+
import pendulum
2222

2323
from airflow import DAG
2424
from airflow.exceptions import AirflowSkipException
@@ -54,6 +54,11 @@ def create_test_pipeline(suffix, trigger_rule):
5454
join >> final
5555

5656

57-
with DAG(dag_id='example_skip_dag', start_date=datetime(2021, 1, 1), catchup=False, tags=['example']) as dag:
57+
with DAG(
58+
dag_id='example_skip_dag',
59+
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
60+
catchup=False,
61+
tags=['example'],
62+
) as dag:
5863
create_test_pipeline('1', TriggerRule.ALL_SUCCESS)
5964
create_test_pipeline('2', TriggerRule.ONE_SUCCESS)

0 commit comments

Comments
 (0)