当将日期字段作为对象发送到键入时间戳的 BigQuery 表时,Google java API 库不会引发异常,但不会引发数据。检查返回的"InsertAllResponse"响应类型包括错误"此字段不是记录"。
例如
Hashmap<String,Object> rowContent = new Hashmap<>();
rowContent.put("Time", new Date());
rowContent.put("Name", "Harry");
然后
BigQuery bq = BigQueryOptions.getDefaultInstance().getService();
TableId tableId = TableId.of(datasetName, tableName);
InsertAllRequest.Builder insertReqBuilder = InsertAllRequest.newBuilder(tableId);
insertReqBuilder.addRow({some string}, row);
InsertAllResponse response = bigquery.insertAll(insertReqBuilder.build());
返回 response.hasErrors(( true。
还在这里报道了python,在这里报道了firebase,在这里报道了javascript。
将日期作为对象发送似乎会导致客户端 API 创建 JSON 记录而不是单个字段(这也表明日期时间类型尚未显式映射,因此可能会引入时区问题(。
相反,将日期/时间作为自 1970 年以来的 UTC秒发送,即修改上述内容:
Hashmap<String,Object> rowContent = new Hashmap<>();
rowContent.put("Time", Math.floor(new Date().getTime()/1000));
rowContent.put("Name", "Harry");
(注意:不知道如何处理毫秒,参见例如 BigQuery 不处理以毫秒为单位的分区列时间戳,我会找出并返回(
不幸的是,BigQuery 的 Java API 在未记录的情况下将 Java 类型转换为 BigQuery 类型。在 BigQuery 时间戳的情况下,Java API 将浮点数和 int 转换为自 Unix epoch 以来的整数截断秒数。这是非常愚蠢的,考虑到几乎每个人都使用毫秒,因为Unix Epoch和时间戳支持高达微秒的精度。如果您可以使用秒,请使用 int 作为秒。
如果需要更高的准确性,请将时间戳值转换为字符串。根据本文档,规范字符串为:
YYYY-[M]M-[D]D[( |T)[H]H:[M]M:[S]S[.DDDDDD]][time zone]
这是一个Java代码示例,其中"毫秒"存储自Unix Epoch以来的毫秒数,但您可以使用您可能碰巧拥有的任何DateTime:
long milliseconds = 1610399564959L;
LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneOffset.UTC);
DateTimeFormatter timestampFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
String timestampText = dateTime.format(timestampFormatter);
rowContent.put("Time", timestampText);
我真的希望谷歌能在某个地方记录这些转换。