Skip to content

Commit bfeedf5

Browse files
committed
fix: use UTC datetime range for date filtering instead of UTC date comparison
- Calculate target_date_start_utc and target_date_end_utc for the target timezone's day - Filter runs using >= and <= with UTC timestamps instead of date casting - Fixes edge cases for timezones significantly offset from UTC (e.g., UTC+10, UTC-10) - Prevents incorrect inclusion/exclusion of runs when local day spans UTC day boundary
1 parent 6fedeec commit bfeedf5

2 files changed

Lines changed: 25 additions & 4 deletions

File tree

macros/edr/tests/test_execution_sla.sql

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@
112112
model_name=model_relation.identifier,
113113
sla_deadline_utc=sla_info.sla_deadline_utc,
114114
target_date=sla_info.target_date,
115+
target_date_start_utc=sla_info.target_date_start_utc,
116+
target_date_end_utc=sla_info.target_date_end_utc,
115117
deadline_passed=sla_info.deadline_passed,
116118
formatted_sla_time=formatted_sla_time,
117119
timezone=timezone
@@ -130,12 +132,12 @@
130132
Build SQL query to check if model was executed before SLA deadline.
131133

132134
Logic:
133-
- Query dbt_run_results for successful runs of this model today
135+
- Query dbt_run_results for successful runs of this model today (using UTC datetime range)
134136
- If any successful run completed before the deadline: SLA met
135137
- If deadline hasn't passed yet: Don't fail (still time)
136138
- Otherwise: SLA missed
137139
#}
138-
{% macro get_execution_sla_query(model_unique_id, model_name, sla_deadline_utc, target_date, deadline_passed, formatted_sla_time, timezone) %}
140+
{% macro get_execution_sla_query(model_unique_id, model_name, sla_deadline_utc, target_date, target_date_start_utc, target_date_end_utc, deadline_passed, formatted_sla_time, timezone) %}
139141

140142
{# Get reference to dbt_run_results table #}
141143
{% set run_results_relation = elementary.get_elementary_relation('dbt_run_results') %}
@@ -149,10 +151,12 @@
149151
sla_deadline as (
150152
select
151153
{{ elementary.edr_cast_as_timestamp("'" ~ sla_deadline_utc ~ "'") }} as deadline_utc,
154+
{{ elementary.edr_cast_as_timestamp("'" ~ target_date_start_utc ~ "'") }} as target_date_start_utc,
155+
{{ elementary.edr_cast_as_timestamp("'" ~ target_date_end_utc ~ "'") }} as target_date_end_utc,
152156
'{{ target_date }}' as target_date
153157
),
154158

155-
{# Get all successful runs for this model today #}
159+
{# Get all runs for this model today (using UTC datetime range for target timezone's day) #}
156160
todays_runs as (
157161
select
158162
rr.unique_id,
@@ -163,7 +167,8 @@
163167
cross join sla_deadline sd
164168
where rr.unique_id = '{{ model_unique_id }}'
165169
and rr.resource_type = 'model'
166-
and cast({{ elementary.edr_cast_as_timestamp('rr.execute_completed_at') }} as date) = cast(sd.deadline_utc as date)
170+
and {{ elementary.edr_cast_as_timestamp('rr.execute_completed_at') }} >= sd.target_date_start_utc
171+
and {{ elementary.edr_cast_as_timestamp('rr.execute_completed_at') }} <= sd.target_date_end_utc
167172
),
168173

169174
successful_runs as (

macros/edr/tests/test_utils/sla_utils.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
Returns: {
3838
'sla_deadline_utc': string (YYYY-MM-DD HH:MM:SS),
3939
'target_date': string (YYYY-MM-DD),
40+
'target_date_start_utc': string (YYYY-MM-DD HH:MM:SS) - start of day in UTC,
41+
'target_date_end_utc': string (YYYY-MM-DD HH:MM:SS) - end of day in UTC,
4042
'deadline_passed': boolean
4143
}
4244
#}
@@ -55,6 +57,16 @@
5557
{# Target date is today in the target timezone #}
5658
{% set target_date_local = now_local.date() %}
5759

60+
{# Create start of day (00:00:00) in target timezone #}
61+
{% set day_start_naive = datetime.datetime.combine(target_date_local, datetime.time(0, 0, 0)) %}
62+
{% set day_start_local = target_tz.localize(day_start_naive, is_dst=False) %}
63+
{% set day_start_utc = day_start_local.astimezone(utc_tz) %}
64+
65+
{# Create end of day (23:59:59.999) in target timezone #}
66+
{% set day_end_naive = datetime.datetime.combine(target_date_local, datetime.time(23, 59, 59)) %}
67+
{% set day_end_local = target_tz.localize(day_end_naive, is_dst=False) %}
68+
{% set day_end_utc = day_end_local.astimezone(utc_tz) %}
69+
5870
{# Create the SLA deadline in target timezone #}
5971
{# Use is_dst=False to resolve ambiguous times during DST transitions to standard time #}
6072
{% set sla_time_local = datetime.time(sla_hour, sla_minute, 0) %}
@@ -70,10 +82,14 @@
7082
{# Format for SQL #}
7183
{% set sla_deadline_utc_str = sla_deadline_utc.strftime('%Y-%m-%d %H:%M:%S') %}
7284
{% set target_date_str = target_date_local.strftime('%Y-%m-%d') %}
85+
{% set day_start_utc_str = day_start_utc.strftime('%Y-%m-%d %H:%M:%S') %}
86+
{% set day_end_utc_str = day_end_utc.strftime('%Y-%m-%d %H:%M:%S') %}
7387

7488
{{ return({
7589
'sla_deadline_utc': sla_deadline_utc_str,
7690
'target_date': target_date_str,
91+
'target_date_start_utc': day_start_utc_str,
92+
'target_date_end_utc': day_end_utc_str,
7793
'deadline_passed': deadline_passed,
7894
'day_of_week': now_local.strftime('%A'),
7995
'day_of_month': now_local.day

0 commit comments

Comments
 (0)