ClickHouse / ClickHouse/clickhouse-java

V2 driver ignores column timezones when reading via getTimestamp

Đang mở
#2,787 16 bình luận 2 reaction 1 người được giao Được @chernser nhận Xem trên GitHub
bug question
Ngôn ngữ chính
Java
Star
1.6k
Fork
636
Merge trung bình
2 ngày 23 giờ
Pull request đã merge (30 ngày)
29

Mô tả

## Description

### Steps to reproduce

When running the program below (see Code Example) I get the following output

```
Table test1 created.
Original Timestamp: 2026-03-12 22:58:08.000 (millis: 1773356288000)
Record inserted.
Read t_tokyo: 2026-03-13 07:58:08.0 (millis: 1773388688000)
Read t_ny: 2026-03-12 18:58:08.0 (millis: 1773341888000)
```

Note that one Timestamp value is inserted for both columns (as number of millis since epoch so it should be timezone independent) but when read back 2 different values are returned that are not equal to the original one.

I believe the issue is in https://github.com/ClickHouse/clickhouse-java/blob/268f1b7227ae16d144e81f09b4f7f71b2c2e59e4/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java#L1086 that completely ignores the column's timezone (`zdt.getTimeZone()`) and uses JVM default timezone to convert `LocalDateTime` value to `java.sql.Timestamp`.

### Expected Behaviour

I expect V2 driver to behave the same way as V1 driver and correctly produce 3 identical timestamps:

```
Table test1 created.
Original Timestamp: 2026-03-12 23:02:25.000 (millis: 1773356545000)
Record inserted.
Read t_tokyo: 2026-03-12 23:02:25.0 (millis: 1773356545000)
Read t_ny: 2026-03-12 23:02:25.0 (millis: 1773356545000)
```

### Code Example

```java

package com.example;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Properties;

public class App {
public static void main(String[] args) {
String url = "jdbc:clickhouse://localhost:8123/default";
Properties props = new Properties();
props.setProperty("user", "default");
props.setProperty("password", "");

try (Connection conn = DriverManager.getConnection(url, props)) {
try (Statement stmt = conn.createStatement()) {
// 1. Create the table
stmt.execute("DROP TABLE IF EXISTS test1");
stmt.execute("CREATE TABLE test1 (" +
" t_tokyo DateTime(3, 'Asia/Tokyo'), " +
" t_ny DateTime(3, 'America/New_York') " +
") ENGINE = MergeTree ORDER BY t_tokyo");
System.out.println("Table test1 created.");
}

// 2. Insert record
Timestamp originalTimestamp = new Timestamp(System.currentTimeMillis());
System.out.println("Original Timestamp: " + originalTimestamp + " (millis: " + originalTimestamp.getTime() + ")");

String insertSql = "INSERT INTO test1 (t_tokyo, t_ny) VALUES (?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
pstmt.setTimestamp(1, originalTimestamp);
pstmt.setTimestamp(2, originalTimestamp);
pstmt.executeUpdate();
System.out.println("Record inserted.");
}

// 3. Read back
String selectSql = "SELECT t_tokyo, t_ny FROM test1";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(selectSql)) {
if (rs.next()) {
Timestamp readTokyo = rs.getTimestamp("t_tokyo");
Timestamp readNy = rs.getTimestamp("t_ny");

System.out.println("Read t_tokyo: " + readTokyo + " (millis: " + readTokyo.getTime() + ")");
System.out.println("Read t_ny: " + readNy + " (millis: " + readNy.getTime() + ")");
} else {
System.out.println("No record found.");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

```

#### Environment
* Client version: 0.9.7
* Language version: 25
* OS: Linux

#### ClickHouse Server
* ClickHouse Server version: 26.2.3.2
* ClickHouse Server non-default settings, if any:

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.