【问题标题】:Timezone problem with spark.sql time functionsspark.sql 时间函数的时区问题
【发布时间】:2021-06-14 13:16:28
【问题描述】:

我正在使用 spark 2.4.7 和以独立模式运行的 pyspark 在 jupyter notebook 上编写一些代码。
我需要将一些时间戳转换为 unix 时间来执行一些操作,但是我注意到一个奇怪的行为,遵循我正在运行的代码:

import pyspark
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from datetime import datetime, timedelta, date

spark = SparkSession.builder \
        .appName("test") \
        .master(n_spark_master)\
        .config("spark.total.executor.cores",n_spark_cores_max)\
        .config("spark.cores.max", n_spark_cores_max)\
        .config("spark.executor.memory",n_spark_executor_memory)\
        .config("spark.executor.cores",n_spark_executor_cores)\
        .enableHiveSupport() \
        .getOrCreate()

print(datetime.now().astimezone().tzinfo)

df = spark.createDataFrame([
    (1, "a"),
    (2, "b"),
    (3, "c"), ], ["dummy1", "dummy2"])

epoch = datetime.utcfromtimestamp(0) df=df.withColumn('epoch',lit(epoch))  
timeFmt = '%Y-%m-%dT%H:%M:%S'  
df= df.withColumn('unix_time_epoch',F.unix_timestamp('epoch', format=timeFmt)) df.show()

输出:

CET
+------+------+-------------------+---------------+
|dummy1|dummy2|              epoch|unix_time_epoch|
+------+------+-------------------+---------------+
|     1|     a|1970-01-01 00:00:00|          -3600|
|     2|     b|1970-01-01 00:00:00|          -3600|
|     3|     c|1970-01-01 00:00:00|          -3600|
+------+------+-------------------+---------------+

来自 spark 2.4.7 的文档:

pyspark.sql.functions.unix_timestamp(timestamp=None, format='yyyy-MM-dd HH:mm:ss')[来源]
使用默认时区和默认语言环境,将具有给定模式('yyyy-MM-dd HH:mm:ss',默认)的时间字符串转换为 Unix 时间戳(以秒为单位),返回 null如果失败。

输出CET 的前一个命令print(datetime.now().astimezone().tzinfo) 应该给我我的本地时区,这确实是机器上的正确时区,因为我在UTC+1。
在 Spark 的 UI 上,我也可以清楚地看到 user.timezone=Europe/Rome.
看起来 spark 正在尝试从 UTC+1 转换为 UTC,因此我得到了输出 unix_time_epoch = -3600,而我希望它是 unix_time_epoch = 0
我已尝试更改为 UTC,因为其他线程建议如下:

import pyspark
from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from datetime import datetime, timedelta, date
import time

os.environ['TZ'] = 'Europe/London'
time.tzset()

spark = SparkSession.builder \
        .appName("test") \
        .master(n_spark_master)\
        .config("spark.total.executor.cores",n_spark_cores_max)\
        .config("spark.cores.max", n_spark_cores_max)\
        .config("spark.executor.memory",n_spark_executor_memory)\
        .config("spark.executor.cores",n_spark_executor_cores)\
        .config('spark.driver.extraJavaOptions', '-Duser.timezone=UTC') \
        .config('spark.executor.extraJavaOptions', '-Duser.timezone=UTC') \
        .config('spark.sql.session.timeZone', 'UTC') \
        .enableHiveSupport() \
        .getOrCreate()

print(datetime.now().astimezone().tzinfo)

df = spark.createDataFrame([
    (1, "a"),
    (2, "b"),
    (3, "c"),
], ["dummy1", "dummy2"])

epoch = datetime.utcfromtimestamp(0)
df=df.withColumn('epoch',lit(epoch))
timeFmt = '%Y-%m-%dT%H:%M:%S'
df = df.withColumn('unix_time_epoch',F.unix_timestamp('epoch', format=timeFmt))
df.show()

但输出是:

GMT
+------+------+-------------------+---------------+
|dummy1|dummy2|              epoch|unix_time_epoch|
+------+------+-------------------+---------------+
|     1|     a|1969-12-31 23:00:00|          -3600|
|     2|     b|1969-12-31 23:00:00|          -3600|
|     3|     c|1969-12-31 23:00:00|          -3600|
+------+------+-------------------+---------------+

我想要实现的是评估 UTC 中的所有内容,而不考虑时区偏移,因为在我所在的罗马,本地时区在一年中 UTC+1 和 UTC+2 之间变化,预期输出应该是这样的:

+------+------+-------------------+---------------+
|dummy1|dummy2|              epoch|unix_time_epoch|
+------+------+-------------------+---------------+
|     1|     a|1970-01-01 00:00:00|              0|
|     2|     b|1970-01-01 00:00:00|              0|
|     3|     c|1970-01-01 00:00:00|              0|
+------+------+-------------------+---------------+

【问题讨论】:

    标签: apache-spark datetime pyspark apache-spark-sql timezone


    【解决方案1】:

    您应该使用os.environ['TZ'] = 'UTC' 而不是Europe/London

    1970 年,英国进行了一项“英国标准时间实验”,在 1968 年 10 月 27 日至 1971 年 10 月 31 日期间,英国的时区全年为 GMT+1。(来源:wiki)。这就是为什么你有一个早 1 小时的时间。

    【讨论】:

      猜你喜欢
      • 2019-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多