diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java index 51599c154cf6..f4a7e41f4d24 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java @@ -480,14 +480,12 @@ public Timestamp getTimestamp(String parameterName) throws SQLException { @Override public Timestamp getTimestamp(int parameterIndex, Calendar calendar) throws SQLException { - Timestamp ts = getTimestamp(parameterIndex); - return BigQueryTemporalUtility.convertTimestampWithCalendar(ts, calendar); + return getTimestamp(parameterIndex); } @Override public Timestamp getTimestamp(String parameterName, Calendar calendar) throws SQLException { - Timestamp ts = getTimestamp(parameterName); - return BigQueryTemporalUtility.convertTimestampWithCalendar(ts, calendar); + return getTimestamp(parameterName); } @Override @@ -877,12 +875,7 @@ public void setTimestamp(String parameterName, Timestamp value) throws SQLExcept public void setTimestamp(String parameterName, Timestamp value, Calendar calendar) throws SQLException { checkClosed(); - this.parameterHandler.setParameter( - parameterName, - BigQueryTemporalUtility.convertTimestampWithCalendar(value, calendar), - Timestamp.class, - BigQueryStatementParameterType.IN, - 0); + setTimestamp(parameterName, value); } @Override diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java index 118161f55f44..5227796a7bf0 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java @@ -644,8 +644,7 @@ public void setTime(int parameterIndex, Time value, Calendar calendar) throws SQ public void setTimestamp(int parameterIndex, Timestamp value, Calendar calendar) throws SQLException { checkClosed(); - setTimestamp( - parameterIndex, BigQueryTemporalUtility.convertTimestampWithCalendar(value, calendar)); + setTimestamp(parameterIndex, value); } @Override diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtility.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtility.java index 4d4771621936..2d3dddd3d38e 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtility.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtility.java @@ -478,24 +478,4 @@ static Time convertTimeWithCalendar(Time time, Calendar cal) { targetCal.set(Calendar.MILLISECOND, defaultCal.get(Calendar.MILLISECOND)); return new Time(targetCal.getTimeInMillis()); } - - /** - * Converts a java.sql.Timestamp by shifting its wall-clock fields into the target Calendar's - * timezone per JDBC specification while preserving nanosecond precision. - */ - static Timestamp convertTimestampWithCalendar(Timestamp timestamp, Calendar cal) { - if (timestamp == null || cal == null) { - return timestamp; - } - ZoneId systemZone = ZoneId.systemDefault(); - ZoneId targetZone = cal.getTimeZone().toZoneId(); - if (systemZone.equals(targetZone)) { - return timestamp; - } - LocalDateTime ldt = timestamp.toLocalDateTime(); - ZonedDateTime zdt = ldt.atZone(targetZone); - Timestamp adjustedTimestamp = Timestamp.from(zdt.toInstant()); - adjustedTimestamp.setNanos(timestamp.getNanos()); - return adjustedTimestamp; - } } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatementTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatementTest.java index bfe907b934f4..363d5973d8f4 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatementTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatementTest.java @@ -33,8 +33,11 @@ import java.util.Calendar; import java.util.HashMap; import java.util.Map; +import java.util.TimeZone; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class BigQueryCallableStatementTest { @@ -820,26 +823,28 @@ public void testGetTimestampParamByName() throws SQLException { assertEquals(expected, actual); } - @Test - public void testGetTimestampParamWithCalByIndex() throws SQLException { + @ParameterizedTest + @ValueSource(strings = {"America/New_York", "Asia/Tokyo"}) + public void testGetTimestampParamWithCalByIndex(String zoneId) throws SQLException { BigQueryCallableStatement statement = new BigQueryCallableStatement(bigQueryConnection, "call testProc('?')"); assertNotNull(statement); - Calendar cal = Calendar.getInstance(); - Timestamp expected = new Timestamp(cal.getTimeInMillis()); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); + Timestamp expected = new Timestamp(1700000000000L); statement.getParameterHandler().setParameter(1, expected, Timestamp.class); Timestamp actual = statement.getTimestamp(1, cal); assertEquals(expected, actual); } - @Test - public void testGetTimestampParamWithCalByName() throws SQLException { + @ParameterizedTest + @ValueSource(strings = {"America/New_York", "Asia/Tokyo"}) + public void testGetTimestampParamWithCalByName(String zoneId) throws SQLException { BigQueryCallableStatement statement = new BigQueryCallableStatement(bigQueryConnection, "call testProc('?')"); assertNotNull(statement); - Calendar cal = Calendar.getInstance(); - Timestamp expected = new Timestamp(cal.getTimeInMillis()); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); + Timestamp expected = new Timestamp(1700000000000L); statement .getParameterHandler() @@ -1050,22 +1055,24 @@ public void testSetTimestampParamByName() throws SQLException { assertEquals(expected, actual); } - @Test - public void testSetTimestampCalParamByName() throws SQLException { + @ParameterizedTest + @ValueSource(strings = {"America/New_York", "Asia/Tokyo"}) + public void testSetTimestampCalParamByName(String zoneId) throws SQLException { BigQueryCallableStatement statement = new BigQueryCallableStatement(bigQueryConnection, "call testProc('?')"); assertNotNull(statement); - Timestamp expectedTimestamp = Timestamp.valueOf("2026-07-17 12:34:56.789"); - Calendar expectedCal = Calendar.getInstance(); + Timestamp expectedTimestamp = new Timestamp(1700000000000L); + Calendar expectedCal = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); statement.setTimestamp(PARAM_KEY, expectedTimestamp, expectedCal); Timestamp actual = statement.getTimestamp(PARAM_KEY); - assertNotNull(actual); + assertEquals(expectedTimestamp, actual); actual = statement.getTimestamp(PARAM_KEY, expectedCal); - assertNotNull(actual); + assertEquals(expectedTimestamp, actual); } ////////// Private helper methods //////////////////////// + private void registerOutParamIndexHelper( int paramIndex, int javaSqlType, Class javaType, StandardSQLTypeName sqlType, int scale) throws SQLException { diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java index 204b92041f7b..970a364c885b 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java @@ -53,6 +53,8 @@ import java.util.TimeZone; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class BigQueryPreparedStatementSettersTest { @@ -234,15 +236,17 @@ public void testSetTimeWithCalendar() throws Exception { assertEquals(originalMillis, cal.getTimeInMillis()); } - @Test - public void testSetTimestampWithCalendar() throws Exception { - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + @ParameterizedTest + @ValueSource(strings = {"America/New_York", "Asia/Tokyo"}) + public void testSetTimestampWithCalendar(String zoneId) throws Exception { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zoneId)); cal.setTimeInMillis(1000000L); long originalMillis = cal.getTimeInMillis(); Timestamp ts = new Timestamp(1700000000000L); preparedStatement.setTimestamp(1, ts, cal); assertEquals(Timestamp.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(ts, preparedStatement.parameterHandler.getParameter(1)); assertEquals(originalMillis, cal.getTimeInMillis()); } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtilityTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtilityTest.java index 4adf052b39e0..598ad57bfab9 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtilityTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryTemporalUtilityTest.java @@ -148,31 +148,6 @@ public void testConvertTimeWithCalendar() { assertThat(resultCal.get(Calendar.SECOND)).isEqualTo(45); } - @Test - public void testConvertTimestampWithCalendar() { - Timestamp ts = Timestamp.valueOf("2026-08-24 15:30:45.123456789"); - Calendar cal = Calendar.getInstance(); - - // Null checks - assertThat(BigQueryTemporalUtility.convertTimestampWithCalendar(null, cal)).isNull(); - assertThat(BigQueryTemporalUtility.convertTimestampWithCalendar(ts, null)).isSameInstanceAs(ts); - - // Same timezone fast-path - Calendar sameZoneCal = Calendar.getInstance(TimeZone.getDefault()); - assertThat(BigQueryTemporalUtility.convertTimestampWithCalendar(ts, sameZoneCal)) - .isSameInstanceAs(ts); - - // Different timezone preserves wall-clock shift and nanoseconds - Calendar tokyoCal = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo")); - Timestamp result = BigQueryTemporalUtility.convertTimestampWithCalendar(ts, tokyoCal); - Instant expectedInstant = - LocalDateTime.of(2026, 8, 24, 15, 30, 45, 123456789) - .atZone(ZoneId.of("Asia/Tokyo")) - .toInstant(); - assertThat(result.getTime()).isEqualTo(expectedInstant.toEpochMilli()); - assertThat(result.getNanos()).isEqualTo(123456789); - } - @Test public void testBoxDateTimeAndDate() { Timestamp ts = diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITCallableStatementTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITCallableStatementTest.java index 82f1b142838e..725167cc5660 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITCallableStatementTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITCallableStatementTest.java @@ -444,17 +444,6 @@ public void testSetterGetterTimestamp() throws SQLException { assertEquals(expected, actual); } - @Test - public void testSetterGetterTimestampCal() throws SQLException { - CallableStatement callableStatement = this.bigQueryConnection.prepareCall("call testProc('?')"); - assertNotNull(callableStatement); - Timestamp expected = new Timestamp(1L); - Calendar cal = Calendar.getInstance(); - callableStatement.setTimestamp(CALLABLE_STMT_PARAM_KEY, expected, cal); - Timestamp actual = callableStatement.getTimestamp(CALLABLE_STMT_PARAM_KEY, cal); - assertEquals(expected, actual); - } - // Block B Tests @Test public void testCallableStatementScriptExecuteUpdate() throws SQLException {