BigQuery 在解析时无法识别时区

Posted

技术标签:

【中文标题】BigQuery 在解析时无法识别时区【英文标题】:BigQuery does not recognise timezones when parsing 【发布时间】:2021-11-10 09:16:14 【问题描述】:

取自official doc:

解析时间戳或格式化时使用时区 用于显示的时间戳。时间戳值本身不存储 特定时区,当您应用时区时它也不会改变 偏移量。

时区由这两个规范之一中的字符串表示 格式:

与协调世界时 (UTC) 或字母 Z 表示 UTC 的偏移量 tz 数据库中的时区名称

示例:2014-09-27 12:30:00.45 America/Los_Angeles

这就是我想要做的:

timestamp = dateutil.parser.isoparse(log['timestamp'])
log['local_timestamp'] = timestamp.strftime("%Y-%m-%d %H:%M:%S") + ' Europe/Zurich'

然后,通过 ApacheBeam Python Dataflow 作业,将此条目写入 BigQuery 并产生以下错误:

There were errors inserting to BigQuery. Will not retry. Errors were ['index': 0, 'errors': ['reason': 'invalid', 'location': 'local_timestamp', 'debugInfo': '', 'message': 'Unrecognized timezone: Europe/Zurich'], 'index': 1, 'errors': ['reason': 'invalid', 'location': 'local_timestamp', 'debugInfo': '', 'message': 'Unrecognized timezone: Europe/Zurich']]

我尝试了不同的格式,例如在时间戳或不同位置的末尾附加+2:00,甚至如示例中所示的America/Los_Angeles。它们都导致无法识别的时区错误。似乎只有 UTC 有效。

是我做错了什么,还是文档不正确,只接受 UTC 时间戳?

谢谢!

【问题讨论】:

您能否提供有关您的设置的更多详细信息?从下面的评论中,您提到您正在使用 python 数据流作业。是否可以提供这项工作后的外观输出?也许它缺少一些特定的标志",例如,如果您将在 bigquery 中使用Europe/Zurich,您可能会遇到问题,但如果您将使用"Europe/Zurich",那没关系。您是否也可以尝试使用:log['local_timestamp'] = timestamp.strftime("%Y-%m-%d %H:%M:%S") + '"Europe/Zurich"',添加"在时区。 嗨 Pjoter,感谢您的评论。你究竟想看什么?上面只写了修改时间戳的行,然后将条目写入 bigquery 表,就是这样。如果我尝试您的建议,我会收到另一个错误: ['reason': 'invalid', 'location': 'local_timestamp', 'debugInfo': '', 'message': 'Could not parse \'2021-09 -16 11:32:11 "Europe/Zurich"\' 作为时间戳。所需格式为 YYYY-MM-DD HH:MM[:SS[.SSSSSS]]'] 您可以尝试使用log['local_timestamp'] = timestamp.strftime("%Y-%m-%d %H:%M:%S") + '.0 Europe/Zurich'timestamp.astimezone(pytz.timezone('Europe/Zurich'))吗? 第一个选项我得到'message': 'Unrecognized timezone: Europe/Zurich' 第二个选项我做了timestamp.astimezone(pytz.timezone('Europe/Zurich')).strftime("%Y-%m-%d %H:%M:%S %Z") 并得到'message': 'Unrecognized timezone: CEST' @PjoterS 的解决方案对我来说听起来很合理。你能检查它是否在没有时间戳解析的情况下工作(strftime):str(timestamp.astimezone(pytz.timezone('Europe/Zurich'))) 但直接使用产生字符串值的str() 函数? 【参考方案1】:

我使用了文档中的基本 code sample 来检查与 Dataflow 流式传输到 Bigquery 功能相关的 tabledata.insertAll 方法,模拟时间戳转换的类似方法。

from google.cloud import bigquery
import dateutil, pytz
import dateutil.parser as dt

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set table_id to the ID of table to append to.
table_id = "your-project.your_dataset.your_table"

t1=dateutil.parser.isoparse('2021-10-20 10:37:24')
t2=str(t1.astimezone(pytz.timezone('Europe/Zurich')))

rows_to_insert = [
    u"t1": t2
]

errors = client.insert_rows_json(table_id, rows_to_insert)  # Make an API request.
if errors == []:
    print("New rows have been added.")
    print (t2)
else:
    print("Encountered errors while inserting rows: ".format(errors))

它正确执行保留时区Europe/Zurich

已添加新行。 2021-10-20 10:37:24+02:00

只要 Bigquery UI 控制台以 UTC 格式保存时间戳,我的测试记录就会被正确转换并插入到目标表中:

希望这能澄清我在 cmets 中所做的努力。

【讨论】:

嗨尼克,感谢您的回答。似乎误会在于时间戳的转换。我有一个 UTC 时间戳,想要可视化 CEST 对应时间,而不是将时区转换为 CEST。 由于 Bigquery 以 UTC 格式保存时间戳,我的目的是证明我的时间戳已正确插入 Bigquery 表,因为 CEST 时区阈值已正确反映在 UTC 时间视图中。如果您想将原始 UTC 记录可视化到自定义区域,请考虑查看特定的 Bigquery datetime 函数。你觉得合理吗?【参考方案2】:

不,BQ 也接受 UTC 时区以外的时区。

SELECT
  CURRENT_TIMESTAMP() AS datetime_ymdhms,
  DATETIME(CURRENT_TIMESTAMP(),
    "Europe/Zurich") AS datetime_tstz;

我猜问题是“欧洲/苏黎世”。你可以试试“欧洲/苏黎世”吗?

【讨论】:

您好,谢谢您的回答。我的问题发生在通过 python 数据流作业插入 bigquery 时解析时间戳,而不是在运行查询时。我试过没有空格的“欧洲/苏黎世”,同样的问题。【参考方案3】:

如果您在 BigQuery 中使用批量插入,您可能需要在加载之前检查临时 Cloud Storage 路径中生成的文件。 有了这些信息,您可以检查它是 Dataflow 问题(很可能是您的代码生成的格式不好)还是 BigQuery 问题(出于任何奇怪的原因,TZ 未被接受)。

【讨论】:

您好,谢谢您的回答。我的管道是流式管道:)

以上是关于BigQuery 在解析时无法识别时区的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 无法识别分区表谓词

BigQuery 无法识别联接中子选择的字段

Mysql时区无法识别

服务器时区值“CEST”无法识别

无法连接到 mySQL,因为无法识别服务器时区值“GMT Summer Time”

Spring Boot 无法连接到 MySQL:无法识别服务器时区值“Mitteleuropäische Zeit”