Airflow Time Zone Conversion Inside Jinja Template

At work, while writing an Airlfow DAG I needed to convert {{ execution_date }} macro from UTC to IST inside Jinja template. Initially I thought {{ execution_date }} gives a datatime object, so converting it inside Jinja template would be tricky as the it requires a tzinfo object.

For example,

from datetime import datetime
from import gettz

utc = gettz("UTC")
utc_now =
print(f"UTC: {utc_now}")
# UTC: 2020-06-17 16:04:04.952171+00:00

ist = gettz("Asia/Kolkata")
ist_now = utc_now.astimezone(ist)
print(f"IST: {ist_now}")
#IST: 2020-06-17 21:34:04.952171+05:30

Luckily, {{ execution_date }} is not a datetime object. Airflow uses Pendulum for datetime and it is an instance of Pendulum. Pendulum class has in_timezone(tz: str) (or in_tz(tz: str)) method that creates a new Pendulum object in the specified time zone.

For example,

from pendulum import datetime

utc_now ="UTC")
print(f"UTC: {utc_now}")
# UTC: 2020-06-17T16:09:29.844393+00:00

ist_now = utc_now.in_timezone("Asia/Kolkata")
print(f"IST: {ist_now}")
# IST: 2020-06-17T21:39:29.844393+05:30

So I just had to do {{ execution_date.in_timezone("Asia/Kolkata") }} for the conversion.

An example DAG:

from datetime import datetime

from airflow import DAG
from airflow.operators.bash_operator import BashOperator

dag = DAG(
  start_date=datetime(year=1993, month=8, day=31)

with dag:
  echo = BashOperator(
      echo UTC: {{ execution_date }}
      echo IST: {{ execution_date.in_timezone('Asia/Kolkata') }}

Log from Airflow:

[2020-06-17 22:01:11,793] {} INFO - Output:
[2020-06-17 22:01:11,799] {} INFO - UTC: 2020-06-17T16:30:37.072299+00:00
[2020-06-17 22:01:11,800] {} INFO - IST: 2020-06-17T22:00:37.072299+05:30
[2020-06-17 22:01:11,800] {} INFO - Command exited with return code 0

Similarly, we can also use it inside any custom operators.

Did you find this article valuable?

Support Arunvel Sriram by becoming a sponsor. Any amount is appreciated!