Skip to content

fix(plugin-snowflake): keep a timestamp offset the date parser cannot represent as text - #2468

Merged
datlechin merged 1 commit into
fix/snowflake-temporal-decodingfrom
fix/snowflake-tz-offset-range
Aug 26, 2026
Merged

fix(plugin-snowflake): keep a timestamp offset the date parser cannot represent as text#2468
datlechin merged 1 commit into
fix/snowflake-temporal-decodingfrom
fix/snowflake-tz-offset-range

Conversation

@datlechin

Copy link
Copy Markdown
Member

Stacked on the Snowflake decoding work. Base is fix/snowflake-temporal-decoding, which now carries #2466's commit and the merged #2467. Retarget to main when that branch lands.

Found by a Codex review of the decoder.

The defect

TIMESTAMP_TZ carries its zone as minutes biased by +1440, so the field can express any offset in a day. The decoder accepted anything under 24 hours and wrote it as a +HH:MM suffix.

DatabaseDateParser.timeZone(fromSuffix:) ends in:

return TimeZone(secondsFromGMT: sign * (hours * 3_600 + minutes * 60)) ?? .gmt

Measured on this toolchain, TimeZone(secondsFromGMT:) returns a zone up to exactly +18:00 and nil at +18:30. So an offset above eighteen hours became nil, the ?? .gmt read it as UTC, and an epoch-zero payload at +18:30 was shown as 18:30 UTC instead of 00:00 UTC: the instant moved by eighteen and a half hours, silently.

The fix

The decoder now emits an offset only when the shared parser can represent it, and keeps the raw text otherwise. A value that cannot survive the round trip is not written in a spelling the reader will misread.

This follows the rule the rest of the decoder already keeps: an encoding that cannot be decoded confidently is returned exactly as it arrived, never turned into a plausible looking value.

Tests

Four cases pinning the boundary: +18:00 and -18:00 decode, +18:30 and -18:30 keep their raw text.

Verified: build PASS, 38/38 across the decoder and escaping suites, SwiftLint 0 violations.

Related, not fixed here

The same review raised a second boundary problem worth recording. The decoder emits proleptic Gregorian dates, which is what Snowflake documents, but DatabaseDateParser builds a Foundation .gregorian calendar that applies the 1582 Julian cutover. A date in the reform gap, 1582-10-05 through 1582-10-14, fails keepsItsDay and does not parse, and an older date resolves to a different absolute day.

The practical effect is limited and is not a regression: an unparsed date still displays as its own correct text, and the picker routing added with the primary fix sends it to the text editor rather than to a picker set to today. What it loses is date-format rendering and charting for pre-1582 values.

Fixing it properly means making the shared parser proleptic, which changes behaviour for every driver, so it belongs with the app-side temporal work rather than here.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@datlechin
datlechin merged commit 27d9620 into fix/snowflake-temporal-decoding Aug 26, 2026
@datlechin
datlechin deleted the fix/snowflake-tz-offset-range branch August 26, 2026 16:32
datlechin added a commit that referenced this pull request Aug 26, 2026
…dpoint sends (#2466)

* fix(plugin-snowflake): decode the wire encodings the query-request endpoint sends

Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7

* fix(plugin-snowflake): give every statement builder one SQL escaper (#2467)

Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7

* fix(plugin-snowflake): keep a timestamp offset the date parser cannot represent as text (#2468)

Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7

* fix(plugin-snowflake): take the affected row count from the statement type, not a column name (#2469)

Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7

* fix(plugin-snowflake): key the shared session on the saved connection and scope Stop to its own driver (#2470)

Claude-Session: https://claude.ai/code/session_01Qk1xfY3vnneRifC22eV2r7

---------

Co-authored-by: Ngo Quoc Dat <datlechin@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant