具有日期时间tzaware对象的Pyspark中的TimeStampType

Apo*_*los 5 python datetime pyspark

我在Pyspark中无法完全理解以下问题。我有以下日期时间对象

utc_now = datetime.now().replace(tzinfo=tz.tzutc())
utc_now # datetime.datetime(2018, 2, 12, 13, 9, 52, 785007, tzinfo=tzutc())
Run Code Online (Sandbox Code Playgroud)

然后创建一个Spark DataFrame

data_df = spark.createDataFrame([Row(date=utc_now)])
Run Code Online (Sandbox Code Playgroud)

当我尝试显示数据框时

data_df.show(10, False)
Run Code Online (Sandbox Code Playgroud)

包含数据的列位于本地时间2小时前

>>> data_df.show(10, False)
+--------------------------+
|date                      |
+--------------------------+
|2018-02-12 15:09:52.785007|
+--------------------------+
Run Code Online (Sandbox Code Playgroud)

并且收集数据将日期时间对象中的时间偏移了两个小时

>>> data_df.collect()
[Row(date=datetime.datetime(2018, 2, 12, 15, 9, 52, 785007))]
Run Code Online (Sandbox Code Playgroud)

区域信息也将被删除。投射到时可以更改此行为TimestampType吗?

MaF*_*aFF 6

TimestampType在 pyspark 中不像在 Pandas 中那样感知 tz,而是传递long ints 并根据您机器的本地时区(默认情况下)显示它们。

话虽如此,您可以使用 'spark.sql.session.timeZone'

from datetime import datetime
from dateutil import tz
from pyspark.sql import Row

utc_now = datetime.now().replace(tzinfo=tz.tzutc())
print(utc_now)

spark.conf.set('spark.sql.session.timeZone', 'Europe/Paris')
data_df = spark.createDataFrame([Row(date=utc_now)])
data_df.show(10, False)
print(data_df.collect())

    2018-02-12 20:41:16.270386+00:00
    +--------------------------+
    |date                      |
    +--------------------------+
    |2018-02-12 21:41:16.270386|
    +--------------------------+

    [Row(date=datetime.datetime(2018, 2, 12, 21, 41, 16, 270386))]


spark.conf.set('spark.sql.session.timeZone', 'UTC')
data_df2 = spark.createDataFrame([Row(date=utc_now)])
data_df2.show(10, False)
print(data_df2.collect())

    +--------------------------+
    |date                      |
    +--------------------------+
    |2018-02-12 20:41:16.270386|
    +--------------------------+

    [Row(date=datetime.datetime(2018, 2, 12, 21, 41, 16, 270386))]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Spark 将其视为 UTC,但在本地时区提供它,因为 Python 仍然具有时区“欧洲/巴黎”

import os, time
os.environ['TZ'] = 'UTC'
time.tzset()
utc_now = datetime.now()
spark.conf.set('spark.sql.session.timeZone', 'UTC')
data_df2 = spark.createDataFrame([Row(date=utc_now)])
data_df2.show(10, False)
print(data_df2.collect())

    +--------------------------+
    |date                      |
    +--------------------------+
    |2018-02-12 20:41:16.807757|
    +--------------------------+

    [Row(date=datetime.datetime(2018, 2, 12, 20, 41, 16, 807757))]
Run Code Online (Sandbox Code Playgroud)

此外,pyspark.sql.module为您提供了两个函数来将时间戳对象转换为与一天中的同一时间对应的另一个对象 ( from_utc_timesamp, to_utc_timestamp)。虽然我不认为你想改变你的日期时间。