【问题标题】:Time zone conversion while loading in snowflake from pyspark从 pyspark 加载雪花时的时区转换
【发布时间】:2022-10-24 15:28:46
【问题描述】:
我正在使用 pyspark 在雪花中编写一个数据框,该数据框有一个带有时间戳的列。我已经使用 spark config 在美国/东部时区设置它,但是当我将它写入雪花时,它默认转换为 UTC。我希望它只在美国/东部。
我应该在雪花火花连接器选项中添加什么来解决我的问题?
PS:我试过 sfOptions["sfTimezone"] = 'America/New_York', sfOptions["sfTimezone"] = 'spark'。
两者都不起作用:(
【问题讨论】:
标签:
pyspark
timezone
snowflake-cloud-data-platform
【解决方案1】:
Spark 只提供了一种时间戳,相当于 Scala/Java Timestamp 类型。它的行为与 Snowflake 中的 TIMESTAMP_LTZ(本地时区)数据类型几乎相同。因此,在 Spark 和 Snowflake 之间传输数据时,Snowflake 建议使用以下方法来正确保存相对于时区的时间:
- 在 Snowflake 中仅使用 TIMESTAMP_LTZ 数据类型。
笔记默认时间戳数据类型映射为 TIMESTAMP_NTZ(无时区),因此您必须显式设置 TIMESTAMP_TYPE_MAPPING 参数才能使用 TIMESTAMP_LTZ。
- 将 Spark 时区设置为 UTC 并在 Snowflake 中使用此时区(即不要为连接器设置 sfTimezone 选项,也不要在 Snowflake 中明确设置时区)。在这种情况下,TIMESTAMP_LTZ 和 TIMESTAMP_NTZ 实际上是等效的。
要设置时区,请将以下行添加到您的 Spark 代码中:
java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("UTC"))
如果您不实施这些方法中的任何一种,则可能会发生不希望的时间修改。例如,考虑以下场景:
- Spark 中的时区设置为 America/New_York。
- Snowflake 中的时区设置为 Europe/Warsaw,这可以通过以下任一方式发生:
- 将连接器的 sfTimezone 设置为 Europe/Warsaw。
- 将连接器的 sfTimezone 设置为雪花,并将雪花中的 TIMEZONE 会话参数设置为欧洲/华沙。
- TIMESTAMP_NTZ 和 TIMESTAMP_LTZ 都在 Snowflake 中使用。
在这种情况下:
-
如果将 Snowflake 中 TIMESTAMP_NTZ 列中表示 12:00:00 的值发送到 Spark,则该值不携带任何时区信息。 Spark 将该值视为纽约的 12:00:00。
-
如果 Spark 将此值 12:00:00(在纽约)发送回 Snowflake 以加载到 TIMESTAMP_LTZ 列中,它会自动转换并加载为 18:00:00(对于华沙时区)。
-
如果随后将此值转换为 Snowflake 中的 TIMESTAMP_NTZ,则用户会看到 18:00:00,这与原始值 12:00:00 不同。
总而言之,Snowflake 建议至少遵循以下规则之一:
- 对 Spark 和 Snowflake 使用相同的时区,最好是 UTC。
- 仅使用 TIMESTAMP_LTZ 数据类型在 Spark 和 Snowflake 之间传输数据。
你看到的行为也有详细解释here。