Normalize timezone-aware create_timer fire_at to naive UTC#1167
Conversation
A timezone-aware fire_at is now converted to naive UTC in create_timer_internal before the CreateTimerAction is built. The wire value was previously correct only implicitly — protobuf's Timestamp.FromDatetime normalizes aware datetimes — so this makes the naive-UTC invariant explicit in SDK code, keeping fire_at safe to compare against current_utc_datetime (always naive UTC) if such comparisons are ever added. The isinstance guard is needed because fire_at may also be the sentinel Timestamp used for indefinite external-event waits. Adds executor-level regression tests: an aware fire_at schedules at the same absolute instant as its naive-UTC equivalent, and replays cleanly against history recorded in naive UTC. Signed-off-by: Albert Callarisa <albert@diagrid.io>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1167 +/- ##
==========================================
+ Coverage 82.78% 82.86% +0.07%
==========================================
Files 123 123
Lines 10127 10129 +2
==========================================
+ Hits 8384 8393 +9
+ Misses 1743 1736 -7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR makes timer scheduling behavior in the workflow durabletask worker explicit and deterministic by normalizing timezone-aware fire_at datetimes to naive UTC before constructing the CreateTimerAction. This aligns timer inputs with the worker’s existing assumption that current_utc_datetime is always naive UTC, avoiding reliance on protobuf serialization side-effects and protecting future clock-comparison logic.
Changes:
- Normalize timezone-aware
datetimevalues passed tocreate_timer_internalinto naive UTC (astimezone(timezone.utc)+replace(tzinfo=None)). - Add executor-level regression tests to ensure timezone-aware
fire_atschedules the same absolute instant as its naive-UTC equivalent. - Add a replay-compatibility test to ensure clean replay against history recorded in naive UTC (sidecar behavior).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
dapr/ext/workflow/_durabletask/worker.py |
Explicitly normalizes aware datetimes to naive UTC prior to building timer actions. |
tests/ext/workflow/durabletask/test_orchestration_executor.py |
Adds regression tests for correct scheduling and replay behavior with timezone-aware fire_at. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Timers created with a timezone-aware
fire_atare now explicitly normalized to naive UTC increate_timer/create_timer_internalbefore theCreateTimerActionis built. Previously the scheduled instant was correct only implicitly, relying on protobuf'sFromDatetimeto normalize aware datetimes at serialization time; making the conversion explicit in the SDK guarantees the naive-UTC invariant that the rest of the worker assumes (current_utc_datetimeis always naive UTC) and protects any future logic that comparesfire_atagainst the workflow clock. Also adds executor-level regression tests covering scheduling with an awarefire_at(same absolute instant as its naive-UTC equivalent) and clean replay against history recorded in naive UTC.