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

Commit 5a04206

Browse files
committed
feat(bigquery): Add support for custom timezones and timestamps
1 parent af90841 commit 5a04206

4 files changed

Lines changed: 360 additions & 1 deletion

File tree

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

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,45 @@ public Builder setMaxStaleness(String maxStaleness) {
215215

216216
abstract Builder setMaxStalenessInner(String maxStaleness);
217217

218+
/**
219+
* Time zone used when parsing timestamp values that do not have specific time zone information
220+
* (e.g. 2024-04-20 12:34:56). The expected format is a IANA timezone string (e.g.
221+
* America/Los_Angeles).
222+
*/
223+
public abstract Builder setTimeZone(String timeZone);
224+
225+
/** Format used to parse DATE values. Supports C-style and SQL-style values. */
226+
public abstract Builder setDateFormat(String dateFormat);
227+
228+
/** Format used to parse DATETIME values. Supports C-style and SQL-style values. */
229+
public abstract Builder setDatetimeFormat(String datetimeFormat);
230+
231+
/** Format used to parse TIME values. Supports C-style and SQL-style values. */
232+
public abstract Builder setTimeFormat(String timeFormat);
233+
234+
/** Format used to parse TIMESTAMP values. Supports C-style and SQL-style values. */
235+
public abstract Builder setTimestampFormat(String timestampFormat);
236+
237+
/**
238+
* Controls the strategy used to match loaded columns to the schema. If not set, a sensible
239+
* default is chosen based on how the schema is provided. If autodetect is used, then columns
240+
* are matched by name. Otherwise, columns are matched by position. This is done to keep the
241+
* behavior backward-compatible. Acceptable values are: POSITION - matches by position. This
242+
* assumes that the columns are ordered the same way as the schema. NAME - matches by name. This
243+
* reads the header row as column names and reorders columns to match the field names in the
244+
* schema.
245+
*/
246+
public abstract Builder setSourceColumnMatch(String sourceColumnMatch);
247+
248+
/**
249+
* A list of strings represented as SQL NULL value in a CSV file. null_marker and null_markers
250+
* can't be set at the same time. If null_marker is set, null_markers has to be not set. If
251+
* null_markers is set, null_marker has to be not set. If both null_marker and null_markers are
252+
* set at the same time, a user error would be thrown. Any strings listed in null_markers,
253+
* including empty string would be interpreted as SQL NULL. This applies to all column types.
254+
*/
255+
public abstract Builder setNullMarkers(List<String> nullMarkers);
256+
218257
/** Creates an {@code ExternalTableDefinition} object. */
219258
@Override
220259
public abstract ExternalTableDefinition build();
@@ -373,6 +412,37 @@ public HivePartitioningOptions getHivePartitioningOptions() {
373412
return getHivePartitioningOptionsInner();
374413
}
375414

415+
/**
416+
* Returns the time zone used when parsing timestamp values that don't have specific time zone
417+
* information.
418+
*/
419+
@Nullable
420+
public abstract String getTimeZone();
421+
422+
/** Returns the format used to parse DATE values. */
423+
@Nullable
424+
public abstract String getDateFormat();
425+
426+
/** Returns the format used to parse DATETIME values. */
427+
@Nullable
428+
public abstract String getDatetimeFormat();
429+
430+
/** Returns the format used to parse TIME values. */
431+
@Nullable
432+
public abstract String getTimeFormat();
433+
434+
/** Returns the format used to parse TIMESTAMP values. */
435+
@Nullable
436+
public abstract String getTimestampFormat();
437+
438+
/** Returns the strategy used to match loaded columns to the schema, either POSITION or NAME. */
439+
@Nullable
440+
public abstract String getSourceColumnMatch();
441+
442+
/** Returns a list of strings represented as SQL NULL value in a CSV file. */
443+
@Nullable
444+
public abstract List<String> getNullMarkers();
445+
376446
@Nullable
377447
abstract HivePartitioningOptions getHivePartitioningOptionsInner();
378448

@@ -454,6 +524,27 @@ com.google.api.services.bigquery.model.ExternalDataConfiguration toExternalDataC
454524
if (getMetadataCacheMode() != null) {
455525
externalConfigurationPb.setMetadataCacheMode(getMetadataCacheMode());
456526
}
527+
if (getTimeZone() != null) {
528+
externalConfigurationPb.setTimeZone(getTimeZone());
529+
}
530+
if (getDateFormat() != null) {
531+
externalConfigurationPb.setDateFormat(getDateFormat());
532+
}
533+
if (getDatetimeFormat() != null) {
534+
externalConfigurationPb.setDatetimeFormat(getDatetimeFormat());
535+
}
536+
if (getTimeFormat() != null) {
537+
externalConfigurationPb.setTimeFormat(getTimeFormat());
538+
}
539+
if (getTimestampFormat() != null) {
540+
externalConfigurationPb.setTimestampFormat(getTimestampFormat());
541+
}
542+
if (getSourceColumnMatch() != null) {
543+
externalConfigurationPb.getCsvOptions().setSourceColumnMatch(getSourceColumnMatch());
544+
}
545+
if (getNullMarkers() != null) {
546+
externalConfigurationPb.getCsvOptions().setNullMarkers(getNullMarkers());
547+
}
457548

458549
return externalConfigurationPb;
459550
}
@@ -654,6 +745,30 @@ static ExternalTableDefinition fromPb(Table tablePb) {
654745
if (tablePb.getMaxStaleness() != null) {
655746
builder.setMaxStaleness(tablePb.getMaxStaleness());
656747
}
748+
if (externalDataConfiguration.getTimeZone() != null) {
749+
builder.setTimeZone(externalDataConfiguration.getTimeZone());
750+
}
751+
if (externalDataConfiguration.getDateFormat() != null) {
752+
builder.setDateFormat(externalDataConfiguration.getDateFormat());
753+
}
754+
if (externalDataConfiguration.getDatetimeFormat() != null) {
755+
builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat());
756+
}
757+
if (externalDataConfiguration.getTimeFormat() != null) {
758+
builder.setTimeFormat(externalDataConfiguration.getTimeFormat());
759+
}
760+
if (externalDataConfiguration.getTimestampFormat() != null) {
761+
builder.setTimestampFormat(externalDataConfiguration.getTimestampFormat());
762+
}
763+
if (externalDataConfiguration.getCsvOptions() != null) {
764+
if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) {
765+
builder.setSourceColumnMatch(
766+
externalDataConfiguration.getCsvOptions().getSourceColumnMatch());
767+
}
768+
if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) {
769+
builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers());
770+
}
771+
}
657772
}
658773
return builder.build();
659774
}
@@ -724,6 +839,30 @@ static ExternalTableDefinition fromExternalDataConfiguration(
724839
if (externalDataConfiguration.getMetadataCacheMode() != null) {
725840
builder.setMetadataCacheMode(externalDataConfiguration.getMetadataCacheMode());
726841
}
842+
if (externalDataConfiguration.getTimeZone() != null) {
843+
builder.setTimeZone(externalDataConfiguration.getTimeZone());
844+
}
845+
if (externalDataConfiguration.getDateFormat() != null) {
846+
builder.setDateFormat(externalDataConfiguration.getDateFormat());
847+
}
848+
if (externalDataConfiguration.getDatetimeFormat() != null) {
849+
builder.setDatetimeFormat(externalDataConfiguration.getDatetimeFormat());
850+
}
851+
if (externalDataConfiguration.getTimeFormat() != null) {
852+
builder.setTimeFormat(externalDataConfiguration.getTimeFormat());
853+
}
854+
if (externalDataConfiguration.getTimestampFormat() != null) {
855+
builder.setTimestampFormat(externalDataConfiguration.getTimeFormat());
856+
}
857+
if (externalDataConfiguration.getCsvOptions() != null) {
858+
if (externalDataConfiguration.getCsvOptions().getSourceColumnMatch() != null) {
859+
builder.setSourceColumnMatch(
860+
externalDataConfiguration.getCsvOptions().getSourceColumnMatch());
861+
}
862+
if (externalDataConfiguration.getCsvOptions().getNullMarkers() != null) {
863+
builder.setNullMarkers(externalDataConfiguration.getCsvOptions().getNullMarkers());
864+
}
865+
}
727866

728867
return builder.build();
729868
}

0 commit comments

Comments
 (0)