From d20960ef335c22e7ca8640f50cf8830a456f3d4c Mon Sep 17 00:00:00 2001 From: Alex Castillo Date: Sat, 7 Nov 2026 00:41:31 -0400 Subject: [PATCH] fix(client-v2): format Duration nanos with Locale.ROOT in durationToTimeString String.format("%09d") used the default locale, so locales with non-ASCII digits (e.g. fa-IR, ar) produced Time64 literals the server cannot parse. Fixes #3308. Signed-off-by: Alex Castillo --- .../com/clickhouse/client/api/DataTypeUtils.java | 2 +- .../clickhouse/client/api/DataTypeUtilsTests.java | 12 ++++++++++++ history/latest/3308.md | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 history/latest/3308.md diff --git a/client-v2/src/main/java/com/clickhouse/client/api/DataTypeUtils.java b/client-v2/src/main/java/com/clickhouse/client/api/DataTypeUtils.java index cc451aef6..ea67265a2 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/DataTypeUtils.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/DataTypeUtils.java @@ -219,7 +219,7 @@ public static String durationToTimeString(Duration duration, int precision) { if (precision > 0 && precision <= 9) { sb.append('.'); // Format nanos with leading zeros, then truncate to precision - String nanosStr = String.format("%09d", nanos); + String nanosStr = String.format(java.util.Locale.ROOT, "%09d", nanos); sb.append(nanosStr, 0, precision); } diff --git a/client-v2/src/test/java/com/clickhouse/client/api/DataTypeUtilsTests.java b/client-v2/src/test/java/com/clickhouse/client/api/DataTypeUtilsTests.java index 54f9a7000..e22cb4e8c 100644 --- a/client-v2/src/test/java/com/clickhouse/client/api/DataTypeUtilsTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/api/DataTypeUtilsTests.java @@ -501,4 +501,16 @@ void testRoundTripConversionsWithDifferentTimezones() { assertEquals(dateTimeInNy.toLocalDate(), LocalDate.of(2024, 7, 4).minusDays(1), "Same instant should be previous day in New York"); } + + @Test(groups = {"unit"}) + public void testDurationToTimeStringIgnoresDefaultLocale() { + java.util.Locale original = java.util.Locale.getDefault(); + try { + java.util.Locale.setDefault(java.util.Locale.forLanguageTag("fa-IR")); + assertEquals(DataTypeUtils.durationToTimeString(Duration.ofSeconds(3661, 123456789), 9), "1:01:01.123456789"); + assertEquals(DataTypeUtils.durationToTimeString(Duration.ofSeconds(1, 5000000), 3), "0:00:01.005"); + } finally { + java.util.Locale.setDefault(original); + } + } } diff --git a/history/latest/3308.md b/history/latest/3308.md new file mode 100644 index 000000000..5b0e52f8e --- /dev/null +++ b/history/latest/3308.md @@ -0,0 +1 @@ +- **[client-v2, jdbc-v2]** Fixed `Duration`/`Time64` parameter rendered with non-ASCII digits under locales like fa-IR/ar-SA (`String.format` used the default locale); now `Locale.ROOT`. (https://github.com/ClickHouse/clickhouse-java/issues/3308)