spark.sql 时间函数的时区问题
Timezone problem with spark.sql time functions
我正在独立模式下使用 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')[source]
Convert time string with given pattern (‘yyyy-MM-dd HH:mm:ss’, by default) to Unix time stamp (in seconds), using the default timezone and the default locale, return null if fail.
输出 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|
+------+------+-------------------+---------------+
您应该使用 os.environ['TZ'] = 'UTC'
而不是 Europe/London
。
1970年,英国进行了一项“英国标准时间实验”,从1968年10月27日到1971年10月31日,英国的时区全年都是GMT+1。(来源:wiki ).这就是为什么你的时间提前了 1 小时。
我正在独立模式下使用 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')[source]
Convert time string with given pattern (‘yyyy-MM-dd HH:mm:ss’, by default) to Unix time stamp (in seconds), using the default timezone and the default locale, return null if fail.
输出 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|
+------+------+-------------------+---------------+
您应该使用 os.environ['TZ'] = 'UTC'
而不是 Europe/London
。
1970年,英国进行了一项“英国标准时间实验”,从1968年10月27日到1971年10月31日,英国的时区全年都是GMT+1。(来源:wiki ).这就是为什么你的时间提前了 1 小时。