Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit dfc2d9a

Browse files
committed
chore: Address last GCA comment
1 parent 5ad05ec commit dfc2d9a

1 file changed

Lines changed: 16 additions & 20 deletions

File tree

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/QueryParameterValue.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ public abstract class QueryParameterValue implements Serializable {
107107
.toFormatter()
108108
.withZone(ZoneOffset.UTC);
109109
// Regex to identify >9 digits in the fraction part (e.g. `.123456789123`)
110-
// Matches the dot, followed by 10+ digits, followed by non-digits (like +00) or end of string
110+
// Matches the dot, followed by 10+ digits (fractional part), followed by non-digits (like `+00`)
111+
// or end of string
111112
private static final Pattern ISO8601_TIMESTAMP_HIGH_PRECISION_PATTERN =
112-
Pattern.compile("(\\.\\d{10,})(?:\\D|$)");
113+
Pattern.compile("\\.(\\d{10,})(?:\\D|$)");
113114

114115
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
115116
private static final DateTimeFormatter timeFormatter =
@@ -550,30 +551,25 @@ private static <T> String valueToStringOrNull(T value, StandardSQLTypeName type)
550551
*/
551552
@VisibleForTesting
552553
static void validateTimestamp(String timestamp) {
553-
// Match if there is greater than nanosecond precision (>9 fractional digits)
554+
// Check if the string has greater than nanosecond precision (>9 digits in fractional second)
554555
Matcher matcher = ISO8601_TIMESTAMP_HIGH_PRECISION_PATTERN.matcher(timestamp);
555556
if (matcher.find()) {
556-
// Group 1 is the fractional part including the dot (e.g., ".123456789123")
557+
// Group 1 is the fractional second part of the ISO8601 string
557558
String fraction = matcher.group(1);
558-
559-
// The fraction part includes the dot, so we check its length.
560-
// It should be at most 13 characters long (. + 12 digits).
561-
if (fraction.length() > 13) {
559+
// Pos 10-12 of the fractional second are guaranteed to be digits. The regex only
560+
// matches the fraction section as long as they are digits.
561+
if (fraction.length() > 12) {
562562
throw new IllegalArgumentException(
563-
"Fractional portion of ISO8601 supports up to picosecond (12 digits)");
563+
"Fractional second portion of ISO8601 only supports up to picosecond (12 digits) in BigQuery");
564564
}
565565

566-
// Truncate to . + 9 digits
567-
String truncatedFraction = fraction.substring(0, 10);
568-
// Replace the entire fractional portion with the nanosecond portion. Digits exceeding the
569-
// nanosecond will be checked separately.
570-
String truncatedTimestamp =
571-
timestamp.replaceFirst(Pattern.quote(fraction), truncatedFraction);
572-
573-
// It is valid as long as DateTimeFormatter doesn't throw an exception AND
574-
// the fractional portion past nanosecond precision is valid (up to picosecond)
575-
checkFormat(truncatedTimestamp, TIMESTAMP_VALIDATOR);
576-
return;
566+
// Replace the entire fractional second portion with just the nanosecond portion.
567+
// The new timestamp will be validated against the JDK's DateTimeFormatter
568+
String truncatedFraction = fraction.substring(0, 9);
569+
timestamp =
570+
new StringBuilder(timestamp)
571+
.replace(matcher.start(1), matcher.end(1), truncatedFraction)
572+
.toString();
577573
}
578574

579575
// It is valid as long as DateTimeFormatter doesn't throw an exception

0 commit comments

Comments
 (0)