如何阻止pyspark中的时间戳删除尾随零



我有Spark数据帧,其中时间戳以毫秒为单位。

+-----------------------+
|CALC_TS                |
+-----------------------+
|2021-01-27 01:35:05.043|
|2021-01-27 01:35:05.043|    
|2021-01-27 01:35:05.043|

我想让它像这样显示微秒:

+--------------------------+
|CALC_TS                   |
+--------------------------+
|2021-01-27 01:35:05.043000|
|2021-01-27 01:35:05.043000|
|2021-01-27 01:35:05.043000|

所以基本上我希望毫秒部分以微秒的形式显示。在上面的例子中,来自第一个数据帧的43毫秒将是43 thousand微秒,如秒数据帧所示。

I have try:

df.withColumn('TIME', to_timestamp('CALC_TS', 'yyyy-MM-dd HH:mm:ss.SSSSSS'))

df.withColumn('TIME', col('CALC_TS').cast("timestamp"))

但是它们给出了相同的结果并且去掉了最后3个0。有办法做到这一点吗?

to_timestamp(timestamp_str[,fmt])接受一个字符串并返回一个时间戳(类型)。如果您的CALC_TS已经是一个时间戳,那么您应该使用df.withColumn('TIME', date_format('CALC_TS','yyyy-MM-dd HH:mm:ss.SSSSSS'))将其格式化为字符串,具有微秒精度。来自Spark参考:

o分数:使用一个或多个(最多9个)连续的'S'字符,例如SSSSSS,用于解析和格式化秒的一小部分。对于解析,可接受的分数长度为[1,连续' S '的个数]。对于格式化,分数长度将被填充为数字Spark支持毫秒级的datetime精度,最多有6位有效数字,但可以解析纳秒,超过部分截断。

对于Spark 2.4,只是为了使看起来像时间戳字段的精度是微秒,也许你可以"伪造"。像这样格式化:date_format('CALC_TS','yyyy-MM-dd HH:mm:ss.SSS000')

您可以使用rpad。

右pad,末尾为零,直到时间戳的预期长度。在您的示例中,长度为26个字符(用于格式yyyy-MM-dd HH:mm:ss.SSSSSS)

from pyspark.sql.functions import *
df.withColumn('CALC_TS_1', col('CALC_TS').cast("timestamp"))
.withColumn('CALC_TS_1', rpad(col('CALC_TS_1').cast('string'),26,'0'))
.show(truncate=False)
+--------------------------+--------------------------+
|CALC_TS                   |CALC_TS_1                 |
+--------------------------+--------------------------+
|2021-01-27 01:35:05.043   |2021-01-27 01:35:05.043000|
|2021-01-27 01:35:05.043567|2021-01-27 01:35:05.043567|
+--------------------------+--------------------------+

如果列CALC_TS是字符串类型,首先使用to_timestampunix_timestamp函数转换为TimestampType,然后使用date_format,您可以将其格式化为以毫秒为单位的6分数:

from pyspark.sql import functions as F
df.printSchema()
#root
# |-- CALC_TS: string (nullable = true)
df1 = df.withColumn(
'TIME',
F.to_timestamp(
F.unix_timestamp('CALC_TS', "yyyy-MM-dd HH:mm:ss.SSS") # seconds
+ F.substring_index('CALC_TS', '.', -1).cast('float') / 1000 # milliseconds part
)
).withColumn(
"TIME_FORMAT",
F.date_format("TIME", "yyyy-MM-dd HH:mm:ss.SSSSSS")
)
df1.show(truncate=False)
#+-----------------------+-----------------------+--------------------------+
#|CALC_TS                |TIME                   |TIME_FORMAT               |
#+-----------------------+-----------------------+--------------------------+
#|2021-01-27 01:35:05.043|2021-01-27 01:35:05.043|2021-01-27 01:35:05.000043|
#|2021-01-27 01:35:05.043|2021-01-27 01:35:05.043|2021-01-27 01:35:05.000043|
#|2021-01-27 01:35:05.043|2021-01-27 01:35:05.043|2021-01-27 01:35:05.000043|
#+-----------------------+-----------------------+--------------------------+
#root
# |-- CALC_TS: string (nullable = true)
# |-- TIME: timestamp (nullable = true)
# |-- TIME_FORMAT: string (nullable = true)

如果列已经是时间戳类型,只需像上面的代码一样使用date_format

最新更新