Skip to content

Commit 494ce85

Browse files
fix: support DATETIME field that has a space between date and time and has only date (#2176)
* fix: support DATETIME field that has a space between date and time and has only date. * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 721908d commit 494ce85

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

google-cloud-bigquerystorage/src/main/java/com/google/cloud/bigquery/storage/v1/JsonToProtoMessage.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,25 @@ public class JsonToProtoMessage implements ToProtoConverter<Object> {
100100
.toFormatter()
101101
.withZone(ZoneOffset.UTC);
102102

103+
private static final DateTimeFormatter DATETIME_FORMATTER =
104+
new DateTimeFormatterBuilder()
105+
.parseLenient()
106+
.append(DateTimeFormatter.ISO_LOCAL_DATE)
107+
.optionalStart()
108+
.optionalStart()
109+
.parseCaseInsensitive()
110+
.appendLiteral('T')
111+
.optionalEnd()
112+
.optionalStart()
113+
.appendLiteral(' ')
114+
.optionalEnd()
115+
.append(DateTimeFormatter.ISO_LOCAL_TIME)
116+
.optionalEnd()
117+
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
118+
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
119+
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
120+
.toFormatter();
121+
103122
/** You can use {@link #INSTANCE} instead */
104123
public JsonToProtoMessage() {}
105124

@@ -402,7 +421,8 @@ private void fillField(
402421
if (val instanceof String) {
403422
protoMsg.setField(
404423
fieldDescriptor,
405-
CivilTimeEncoder.encodePacked64DatetimeMicros(LocalDateTime.parse((String) val)));
424+
CivilTimeEncoder.encodePacked64DatetimeMicros(
425+
LocalDateTime.parse((String) val, DATETIME_FORMATTER)));
406426
return;
407427
} else if (val instanceof Long) {
408428
protoMsg.setField(fieldDescriptor, val);
@@ -663,7 +683,8 @@ private void fillRepeatedField(
663683
if (val instanceof String) {
664684
protoMsg.addRepeatedField(
665685
fieldDescriptor,
666-
CivilTimeEncoder.encodePacked64DatetimeMicros(LocalDateTime.parse((String) val)));
686+
CivilTimeEncoder.encodePacked64DatetimeMicros(
687+
LocalDateTime.parse((String) val, DATETIME_FORMATTER)));
667688
} else if (val instanceof Long) {
668689
protoMsg.addRepeatedField(fieldDescriptor, val);
669690
} else {

google-cloud-bigquerystorage/src/test/java/com/google/cloud/bigquery/storage/v1/JsonToProtoMessageTest.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ public void testDateTimeMismatch() throws Exception {
608608
TableFieldSchema.newBuilder()
609609
.setName("datetime")
610610
.setType(TableFieldSchema.Type.DATETIME)
611-
.setMode(TableFieldSchema.Mode.REPEATED)
611+
.setMode(TableFieldSchema.Mode.NULLABLE)
612612
.build();
613613
TableSchema tableSchema = TableSchema.newBuilder().addFields(field).build();
614614
JSONObject json = new JSONObject();
@@ -623,6 +623,34 @@ public void testDateTimeMismatch() throws Exception {
623623
}
624624
}
625625

626+
private void dateTimeMatch_Internal(String jsonVal, Long expectedVal) throws Exception {
627+
TableFieldSchema field =
628+
TableFieldSchema.newBuilder()
629+
.setName("datetime")
630+
.setType(TableFieldSchema.Type.DATETIME)
631+
.setMode(TableFieldSchema.Mode.NULLABLE)
632+
.build();
633+
TableSchema tableSchema = TableSchema.newBuilder().addFields(field).build();
634+
TestDatetime expectedProto = TestDatetime.newBuilder().setDatetime(expectedVal).build();
635+
JSONObject json = new JSONObject();
636+
json.put("datetime", jsonVal);
637+
DynamicMessage protoMsg =
638+
JsonToProtoMessage.INSTANCE.convertToProtoMessage(
639+
TestDatetime.getDescriptor(), tableSchema, json);
640+
assertEquals(expectedProto, protoMsg);
641+
}
642+
643+
@Test
644+
public void testDateTimeMatch() throws Exception {
645+
dateTimeMatch_Internal("2021-09-27T20:51:10.752", 142258614586538368L);
646+
dateTimeMatch_Internal("2021-09-27t20:51:10.752", 142258614586538368L);
647+
dateTimeMatch_Internal("2021-09-27 20:51:10.752", 142258614586538368L);
648+
dateTimeMatch_Internal("2021-9-27T20:51:10.752", 142258614586538368L);
649+
dateTimeMatch_Internal("2021-09-27T00:00:00", 142258525253402624L);
650+
dateTimeMatch_Internal("2021-09-27T00:0:00", 142258525253402624L);
651+
dateTimeMatch_Internal("2021-09-27", 142258525253402624L);
652+
}
653+
626654
@Test
627655
public void testTimeMismatch() throws Exception {
628656
TableFieldSchema field =
@@ -952,6 +980,9 @@ public void testStructComplex() throws Exception {
952980
.setTestDate(1)
953981
.setTestDatetime(1)
954982
.addTestDatetimeStr(142258614586538368L)
983+
.addTestDatetimeStr(142258614586538368L)
984+
.addTestDatetimeStr(142258614586538368L)
985+
.addTestDatetimeStr(142258525253402624L)
955986
.addTestDatetimeStr(142258525253402624L)
956987
.setComplexLvl1(
957988
ComplexLvl1.newBuilder()
@@ -1020,7 +1051,14 @@ public void testStructComplex() throws Exception {
10201051
json.put("test_datetime", 1);
10211052
json.put(
10221053
"test_datetime_str",
1023-
new JSONArray(new String[] {"2021-09-27T20:51:10.752", "2021-09-27T00:00:00"}));
1054+
new JSONArray(
1055+
new String[] {
1056+
"2021-09-27T20:51:10.752",
1057+
"2021-09-27t20:51:10.752",
1058+
"2021-09-27 20:51:10.752",
1059+
"2021-09-27T00:00:00",
1060+
"2021-09-27"
1061+
}));
10241062
json.put("complex_lvl1", complex_lvl1);
10251063
json.put("complex_lvl2", complex_lvl2);
10261064
json.put(

0 commit comments

Comments
 (0)