通过 BigQuery 库发送的时间戳对象返回错误"This field is not a record"



当将日期字段作为对象发送到键入时间戳的 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);

我真的希望谷歌能在某个地方记录这些转换。

相关内容

  • 没有找到相关文章