spark从MySQL中读取一个表,其中有一个存储UTC时区值的时间戳列。Spark在本地(IST)配置。MySQL在时间戳值下面存储。
spark.conf.set("spark.sql.session.timeZone" , "UTC")
df.show(100,False)
使用上面的配置文件后,我可以看到正确的记录与df.show()
。稍后df.rdd.collect()
将这些值转换回IST时区。
for row in df.rdd.collect():
print("row.Mindate ",row.Mindate)
row.Mindate 2021-03-02 19:30:31
row.Mindate 2021-04-01 14:05:03
row.Mindate 2021-06-15 11:39:40
row.Mindate 2021-07-07 18:14:17
row.Mindate 2021-08-03 10:48:51
row.Mindate 2021-10-06 10:21:11
SparkDataFrame和DF.rdd显示了不同结果集。即使在"spark.sql.session.timeZone" , "UTC"
之后,它如何将值更改回本地时区。
先谢谢你了
编辑1:
def.printSchema()
root
|-- Mindate: timestamp (nullable = true)
|-- Maxdate: timestamp (nullable = true)
2条答案
按热度按时间h9a6wy2h1#
解决方案
确保Spark时区(
spark.sql.session.timeZone
)设置为与Python时区(TZ
环境变量)相同的时区。Spark将在调用DataFrame.collect()
时在两者之间转换。您可以按如下方式执行此操作:问题详情
我遇到过完全相同的问题,每当我从Spark收集DataFrame到Python时,都会转换时间戳。我写了下面这个简单的测试来确认行为:
失败,返回消息
datetime.datetime(1970, 1, 1, 11, 0) != datetime.datetime(1970, 1, 1, 10, 0)
。当DataFrame从Spark TimeStampType收集到Python的datetime.datetime
时,时间戳从UTC转换为我的系统默认值(CET)。我不知道为什么会这样,但事情就是这样...正如@Kashyap也指出的那样,我试着查看了源代码,但真的不明白为什么会发生这种情况。Python时区默认为系统默认时区,可以通过
TZ
系统变量进行配置。参见Python文档因此,只要Python的时区和Spark的时区设置之间存在差异,就会发生转换。我们可以如下检查:
gcuhipw92#
TL;DR
collect()将timestamp列(UTC)转换为pyspark中的本地时区(IST)
不,不是的。事实上,你读取的 Dataframe 中的时间戳没有时区。您看到的只是
show()
基于会话本地时区的行为。在
TimestampType
类型的列中存储datetime.datetime
值时时区信息丢失如所述in the docs
日期时间类型
正如你在代码中看到的,
TimestampType
是pythondatetime.datetime
的 Package 器,但是它去掉了时区,并在内部将其存储为epoch time。更多示例代码:
输出中的注解:
DF :
和RDD :
(参见来自print_df_info()
的日志)具有完全相同的内容。它们是相同数据上的不同立面。1.更改
spark.sql.session.timeZone
对“内部表示”没有影响。参见print_df_info()
的日志。1.更改
spark.sql.session.timeZone
将更改show()
打印timestamp
类型值的方式。一些参考文献: