Skip to content

Commit 31213f8

Browse files
test(bigquery): Add tests to verify lossless max timestamp parsing (#12892)
b/326260769 --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 8a25165 commit 31213f8

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

java-bigquery/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/FieldValueTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,18 @@ public void testInt64Timestamp() {
151151
assertEquals(expected, received);
152152
}
153153

154+
@Test
155+
public void testLosslessMaxTimestamp() {
156+
// Test the lossless behavior (useInt64Timestamps = true)
157+
// The backend returns a 64-bit integer string for microseconds when this option is enabled
158+
String losslessTimestampString = "253402300799999999";
159+
FieldValue losslessValue =
160+
FieldValue.of(FieldValue.Attribute.PRIMITIVE, losslessTimestampString, true);
161+
162+
// Exactly matches the microsecond equivalent of 9999-12-31 23:59:59.999999
163+
assertEquals(253402300799999999L, losslessValue.getTimestampValue());
164+
}
165+
154166
@Test
155167
public void testEquals() {
156168
FieldValue booleanValue = FieldValue.of(FieldValue.Attribute.PRIMITIVE, "false");

java-bigquery/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,56 @@ static GoogleCredentials loadCredentials(String credentialFile) {
12151215
}
12161216
}
12171217

1218+
@Test
1219+
void testLosslessMaxTimestampIntegration() throws InterruptedException {
1220+
String query = "SELECT TIMESTAMP '9999-12-31 23:59:59.999999 UTC' as max_ts";
1221+
QueryJobConfiguration config = QueryJobConfiguration.newBuilder(query).build();
1222+
1223+
// 1. Test lossless 64-bit integer parsing (useInt64Timestamps = true)
1224+
DataFormatOptions losslessOptions =
1225+
DataFormatOptions.newBuilder().useInt64Timestamp(true).build();
1226+
BigQuery losslessBigQuery =
1227+
bigquery.getOptions().toBuilder()
1228+
.setDataFormatOptions(losslessOptions)
1229+
.build()
1230+
.getService();
1231+
1232+
TableResult losslessResult = losslessBigQuery.query(config);
1233+
assertEquals(1L, losslessResult.getTotalRows());
1234+
for (FieldValueList row : losslessResult.iterateAll()) {
1235+
long exactMicros = row.get("max_ts").getTimestampValue();
1236+
assertEquals(253402300799999999L, exactMicros);
1237+
}
1238+
1239+
// 2. Test lossy FLOAT64 rounding behavior (useInt64Timestamps = false)
1240+
DataFormatOptions floatOptions =
1241+
DataFormatOptions.newBuilder().useInt64Timestamp(false).build();
1242+
BigQuery floatBigQuery =
1243+
bigquery.getOptions().toBuilder().setDataFormatOptions(floatOptions).build().getService();
1244+
1245+
TableResult floatResult = floatBigQuery.query(config);
1246+
assertEquals(1L, floatResult.getTotalRows());
1247+
for (FieldValueList row : floatResult.iterateAll()) {
1248+
long roundedMicros = row.get("max_ts").getTimestampValue();
1249+
assertEquals(253402300800000000L, roundedMicros);
1250+
}
1251+
1252+
// 3. Test ISO8601 timestamp formatting
1253+
DataFormatOptions isoOptions =
1254+
DataFormatOptions.newBuilder()
1255+
.timestampFormatOptions(DataFormatOptions.TimestampFormatOptions.ISO8601_STRING)
1256+
.build();
1257+
BigQuery isoBigQuery =
1258+
bigquery.getOptions().toBuilder().setDataFormatOptions(isoOptions).build().getService();
1259+
1260+
TableResult isoResult = isoBigQuery.query(config);
1261+
assertEquals(1L, isoResult.getTotalRows());
1262+
for (FieldValueList row : isoResult.iterateAll()) {
1263+
String isoValue = row.get("max_ts").getStringValue();
1264+
assertEquals("9999-12-31T23:59:59.999999Z", isoValue);
1265+
}
1266+
}
1267+
12181268
@Test
12191269
void testListDatasets() {
12201270
Page<Dataset> datasets = bigquery.listDatasets("bigquery-public-data");

0 commit comments

Comments
 (0)