Skip to content

Commit b47df2a

Browse files
Fix fusion pytz.localize() producing incorrect results in calculate_sla_deadline_utc
In dbt-fusion, pytz.localize() produces incorrect timezone-aware datetimes, causing deadline_passed to be False when it should be True. Use datetime.timezone.utc and replace(tzinfo=) in the fusion path instead. Co-Authored-By: Itamar Hartstein <haritamar@gmail.com>
1 parent e83c89c commit b47df2a

1 file changed

Lines changed: 57 additions & 35 deletions

File tree

macros/edr/tests/test_utils/sla_utils.sql

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -59,41 +59,63 @@
5959
{% set datetime = modules.datetime %}
6060
{% set pytz = modules.pytz %}
6161

62-
{# Get timezone objects #}
63-
{% set utc_tz = pytz.timezone("UTC") %}
64-
{% set target_tz = pytz.timezone(timezone) %}
65-
66-
{# Get current time in UTC and target timezone #}
67-
{% set now_utc = datetime.datetime.now(utc_tz) %}
68-
{% set now_local = now_utc.astimezone(target_tz) %}
69-
70-
{# Target date is today in the target timezone #}
71-
{% set target_date_local = now_local.date() %}
72-
73-
{# Create start of day (00:00:00) in target timezone #}
74-
{% set day_start_naive = datetime.datetime.combine(
75-
target_date_local, datetime.time(0, 0, 0)
76-
) %}
77-
{% set day_start_local = target_tz.localize(day_start_naive, is_dst=False) %}
78-
{% set day_start_utc = day_start_local.astimezone(utc_tz) %}
79-
80-
{# Create end of day (23:59:59.999) in target timezone #}
81-
{% set day_end_naive = datetime.datetime.combine(
82-
target_date_local, datetime.time(23, 59, 59)
83-
) %}
84-
{% set day_end_local = target_tz.localize(day_end_naive, is_dst=False) %}
85-
{% set day_end_utc = day_end_local.astimezone(utc_tz) %}
86-
87-
{# Create the SLA deadline in target timezone #}
88-
{# Use is_dst=False to resolve ambiguous times during DST transitions to standard time #}
89-
{% set sla_time_local = datetime.time(sla_hour, sla_minute, 0) %}
90-
{% set sla_deadline_naive = datetime.datetime.combine(
91-
target_date_local, sla_time_local
92-
) %}
93-
{% set sla_deadline_local = target_tz.localize(sla_deadline_naive, is_dst=False) %}
94-
95-
{# Convert to UTC #}
96-
{% set sla_deadline_utc = sla_deadline_local.astimezone(utc_tz) %}
62+
{# In dbt-fusion, pytz.localize() produces incorrect results (dbt-labs/dbt-fusion#143).
63+
Use datetime.timezone.utc and replace(tzinfo=) instead. #}
64+
{% if elementary.is_dbt_fusion() %}
65+
{% set utc_tz = datetime.timezone.utc %}
66+
{% set target_tz = pytz.timezone(timezone) %}
67+
68+
{% set now_utc = datetime.datetime.now(utc_tz) %}
69+
{% set now_local = now_utc.astimezone(target_tz) %}
70+
{% set target_date_local = now_local.date() %}
71+
72+
{# Use replace(tzinfo=) instead of localize() for fusion compatibility #}
73+
{% set day_start_naive = datetime.datetime.combine(
74+
target_date_local, datetime.time(0, 0, 0)
75+
) %}
76+
{% set day_start_local = day_start_naive.replace(tzinfo=target_tz) %}
77+
{% set day_start_utc = day_start_local.astimezone(utc_tz) %}
78+
79+
{% set day_end_naive = datetime.datetime.combine(
80+
target_date_local, datetime.time(23, 59, 59)
81+
) %}
82+
{% set day_end_local = day_end_naive.replace(tzinfo=target_tz) %}
83+
{% set day_end_utc = day_end_local.astimezone(utc_tz) %}
84+
85+
{% set sla_deadline_naive = datetime.datetime.combine(
86+
target_date_local, datetime.time(sla_hour, sla_minute, 0)
87+
) %}
88+
{% set sla_deadline_local = sla_deadline_naive.replace(tzinfo=target_tz) %}
89+
{% set sla_deadline_utc = sla_deadline_local.astimezone(utc_tz) %}
90+
{% else %}
91+
{# Standard dbt-core path using pytz.localize() #}
92+
{% set utc_tz = pytz.timezone("UTC") %}
93+
{% set target_tz = pytz.timezone(timezone) %}
94+
95+
{% set now_utc = datetime.datetime.now(utc_tz) %}
96+
{% set now_local = now_utc.astimezone(target_tz) %}
97+
{% set target_date_local = now_local.date() %}
98+
99+
{% set day_start_naive = datetime.datetime.combine(
100+
target_date_local, datetime.time(0, 0, 0)
101+
) %}
102+
{% set day_start_local = target_tz.localize(day_start_naive, is_dst=False) %}
103+
{% set day_start_utc = day_start_local.astimezone(utc_tz) %}
104+
105+
{% set day_end_naive = datetime.datetime.combine(
106+
target_date_local, datetime.time(23, 59, 59)
107+
) %}
108+
{% set day_end_local = target_tz.localize(day_end_naive, is_dst=False) %}
109+
{% set day_end_utc = day_end_local.astimezone(utc_tz) %}
110+
111+
{% set sla_deadline_naive = datetime.datetime.combine(
112+
target_date_local, datetime.time(sla_hour, sla_minute, 0)
113+
) %}
114+
{% set sla_deadline_local = target_tz.localize(
115+
sla_deadline_naive, is_dst=False
116+
) %}
117+
{% set sla_deadline_utc = sla_deadline_local.astimezone(utc_tz) %}
118+
{% endif %}
97119

98120
{# Check if deadline has passed #}
99121
{% set deadline_passed = now_utc > sla_deadline_utc %}

0 commit comments

Comments
 (0)