fix(source-zendesk-support): render epoch cursor boundaries in UTC, not the host timezone - #84354
Conversation
…ot the host timezone
`cursor_incremental_sync.start_datetime` and the `tickets_search` cursor rendered
their unix-epoch boundaries with `strftime('%s')`. Python does not implement `%s`;
`strftime` hands it to the C library, which ignores the datetime's tzinfo and
applies the host's timezone. The rendered epoch is therefore shifted by the host's
UTC offset, so the request window is wrong on any non-UTC host.
Use `.timestamp() | int` instead, and replace `day_delta(-730, '%s')` with
`(now_utc() - duration('P730D')).timestamp() | int` — `day_delta` applies
`strftime` internally and carries the same defect when asked for `%s`.
Airbyte's job containers run UTC, where both forms agree, which is why this went
unnoticed. It surfaced as two `tickets_search` unit tests that pass in CI and fail
on any developer machine outside UTC with `NoMockAddress`, the rendered query
window not matching the mock. Verified across UTC, Europe/Kyiv,
America/Los_Angeles and Asia/Kolkata (half-hour offset).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Note 📝 PR Converted to Draft More info...Thank you for creating this PR. As a policy to protect our engineers' time, Airbyte requires all PRs to be created first in draft status. Your PR has been automatically converted to draft status in respect for this policy. As soon as your PR is ready for formal review, you can proceed to convert the PR to "ready for review" status by clicking the "Ready for review" button at the bottom of the PR page. To skip draft status in future PRs, please include |
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksPR Slash CommandsAirbyte Maintainers (that's you!) can execute the following slash commands on your PR:
📚 Show Repo GuidanceHelpful Resources
|
Detected
|
|
Deploy preview for airbyte-docs ready!
Deployed with vercel-action |
|
|
What
Two
tickets_searchunit tests pass in CI and fail on any developer machine outside UTC:The tests are correct. The manifest is not.
cursor_incremental_sync.start_datetimeand thetickets_searchcursor both render unix-epoch boundaries withstrftime('%s'):Python does not implement
%s—strftimedelegates it to the C library, which ignores the datetime'stzinfoand applies the host's timezone. So the rendered epoch is shifted by the host's UTC offset, and the request window is wrong. Measured on the same frozen instant:Airbyte's job containers run UTC, where both forms agree — which is why this has gone unnoticed. The CDK's own
DatetimeParserspecial-cases%son both parse and format paths for precisely this reason, with the comment "strftime('%s') is unreliable because it ignores the time zone information and assumes the time zone of the system it's running on". The manifest was doing the thing the CDK carefully avoids.How
Render epochs with
.timestamp() | int, which respectstzinfo:day_delta(num_days, format)appliesstrftimeinternally, so it carries the same defect wheneverformatis'%s';now_utc() - duration('P730D')replaces it. The two remainingday_deltacalls in the manifest request'%Y-%m-%dT%H:%M:%SZ'and are unaffected — that directive is implemented by Python and is timezone-correct.timestamp(...)was already safe and is unchanged.Verified identical output across
UTC,Europe/Kyiv,America/Los_AngelesandAsia/Kolkata(deliberately included for its half-hour offset).Declarative-First Evaluation
Declarative only — three interpolation expressions. No Python component involved; the correct primitives already existed in the CDK's macro set.
Breaking Change Evaluation
Not breaking, and no production behavior change: Airbyte job containers run UTC, where the old and new expressions render the same epoch. What changes is correctness off UTC — a self-managed deployment on a non-UTC host was requesting windows shifted by its offset. Version
5.5.2.Test Coverage
No new tests. The two existing tests above already assert the exact query window; they were failing for the right reason and now pass. Full connector suite, run twice:
mock_server/test_tickets.pyspecifically, across four zones:Before this change, both non-UTC full-suite runs reported
2 failed.Review guide
manifest.yaml— three expressions, plus a comment atcursor_incremental_sync.start_datetimeexplaining why%sis banned here.AGENTS.md§5 — the rule and the symptom, so the next person writing an epoch cursor does not reintroduce it.Note on version collision
#84353 (a
side_conversationserror-handling fix) also targets5.5.2. Whichever merges second needs a bump to5.5.3and a changelog line move. The two PRs otherwise touch disjoint parts of the manifest.Can this PR be safely reverted and rolled back?
Important
Active progressive rollout warning for source-zendesk-support.