Skip to content

fix(jdbc-v2): preserve DateTime column timezone in getTimestamp - #2991

Closed
arimu1 wants to merge 1 commit into
ClickHouse:mainfrom
arimu1:fix/2787-gettimestamp-column-timezone
Closed

fix(jdbc-v2): preserve DateTime column timezone in getTimestamp#2991
arimu1 wants to merge 1 commit into
ClickHouse:mainfrom
arimu1:fix/2787-gettimestamp-column-timezone

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown

Summary

Fixes ResultSet.getTimestamp / getObject(..., Timestamp.class) ignoring the column timezone for DateTime / DateTime32 / DateTime64 values (#2787).

BinaryStreamReader already attaches the column (or server/session) timezone when building the internal ZonedDateTime. The JDBC layer was then converting via the caller Calendar / JVM default, re-interpreting wall-clock components and shifting the returned epoch when that timezone differed from the column's (e.g. DateTime64(3, 'UTC') under a non-UTC JVM, or two columns with different declared timezones).

Changes

  • ResultSetImpl.getTimestamp: convert using the zone on the ZonedDateTime (column/server zone), not the caller Calendar
  • JdbcUtils.convert: preserve absolute instant when converting ZonedDateTime / OffsetDateTime / InstantTimestamp
  • DetachedResultSet.getTimestamp: return the already-materialised absolute Timestamp without re-shifting wall-clock components
  • Unit tests for conversion; integration test for multi-timezone column round-trip
  • CHANGELOG.md + docs/features.md

Compatibility

  • User-visible: getTimestamp for zoned DateTime* columns now returns the correct epoch millis (matching the wire instant). Callers that previously compensated by passing a column-matching Calendar still get the correct value; callers that relied on the incorrect Calendar reinterpretation will see corrected millis.
  • JDBC Calendar parameter remains on the API but is not used to re-shift values that already carry timezone information (matches the JDBC javadoc intent for types that store timezone context).

Test plan

  • mvn -pl client-v2 test -Dtest=DataTypeUtilsTests (39 tests, unit)
  • mvn -pl jdbc-v2 test -Dtest=JdbcUtilsTest (16 tests, unit)
  • CI integration: JDBCDateTimeTests.testGetTimestampPreservesInstantAcrossColumnTimezones (requires ClickHouse)

Fixes #2787

ResultSet.getTimestamp was converting ZonedDateTime via the caller Calendar
(JVM default), reinterpreting wall-clock components and shifting the epoch
when the column timezone differed from the Calendar. Convert using the
column/server zone already attached by the binary reader so the absolute
instant is preserved across columns with different declared timezones.

Fixes ClickHouse#2787
@arimu1
arimu1 requested review from chernser and mzitnik as code owners August 1, 2026 03:30
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 77ee79b. Configure here.

}
wasNull = false;

return DataTypeUtils.toSqlTimestamp(zdt.toLocalDateTime(), cal.getTimeZone());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getTime disagrees with getTimestamp

Medium Severity

getTimestamp now converts DateTime* values using the column zone so epoch millis match the wire instant, but getTime still takes the column wall-clock LocalDateTime and anchors it with the caller Calendar timezone. On the same row, getTimestamp and getTime can disagree whenever the column timezone and Calendar differ.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 77ee79b. Configure here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arimu1
This is very correct comment. Calendar used to reinterpret timestamp internal value to make it work according to spec.

@chernser

chernser commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

@arimu1

Thank you for the contribution!
However fix breaks behavior of the driver - calendar should be used to cast instant to specific timezone.
Most users should migrate to new time framework because it provide more reliable way to work with timestamps.

I'm closing the PR. Please feel free to start discussion in the original issue.

Thanks!

@chernser chernser closed this Aug 1, 2026
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.

V2 driver ignores column timezones when reading via getTimestamp

3 participants