You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySpark拆分日期时间字符串为日期和时间时遇null值问题排查

问题分析与解决

原始数据

读取的CSV数据如下:

PurchaseDatetimePurchaseId
29/08/2020 10:09:019
5/10/2020 7:024
5/10/2020 9:006
20/06/2020 02:11:364
23/10/2020 07:02:153
6/2/2020 10:107

第2、3、6行的PurchaseDatetime缺少秒部分,格式与其他行不一致。

尝试的代码

我用以下代码清洗数据并拆分日期和时间列:

df=df.withColumn("PurchaseDate",to_date(col("PurchaseDatetime"),"dd/MM/yyyy HH:mm:ss")).withColumn("PurchaseTime",date_format("PurchaseDatetime","dd/MM/yyyy HH:mm:ss a"))

期望输出

希望得到如下格式的结果:

PurchaseDatePurchaseTimePurchaseIdPurchaseDatetime
29-08-202010:09:01929/08/2022 10:09:01
05-10-202007:02:0045/10/2020 7:02
05-10-202009:00:0065/10/2020 9:00
20-06-202002:11:36420/06/2020 02:11:36
23-10-202007:02:15323/10/2020 07:02:15
06-02-202010:10:0076/2/2020 10:10

实际结果

但运行后PurchaseTime列全部为null:

PurchaseDatePurchaseTimePurchaseIdPurchaseDatetime
29-08-2020null929/08/2020 10:09:01
05-10-2020null45/10/2020 7:02
05-10-2020null65/10/2020 9:00
20-06-2020null420/06/2020 02:11:36
23-10-2020null323/10/2020 07:02:15
06-02-2020null76/2/2020 10:10

原因分析

  1. date_format参数类型错误:date_format要求第一个参数是时间戳类型(TimestampType),但你直接传入了字符串类型的PurchaseDatetime列,Spark无法直接解析字符串格式的时间,因此返回null。
  2. 时间格式不统一:to_date仅指定了带秒的格式dd/MM/yyyy HH:mm:ss,虽然部分行能兼容解析,但本质上未完成统一的时间类型转换,后续拆分时间的操作自然失效。
  3. 格式字符串不符合需求:你使用的dd/MM/yyyy HH:mm:ss a包含日期部分和AM/PM标识,和你想要的仅时间部分的输出不匹配。

解决方法

正确步骤是先将字符串统一转换为时间戳类型,再拆分日期和时间列:

方法1:多格式解析时间戳(Spark 3.0+支持)

from pyspark.sql import functions as F

# 转换为时间戳,同时支持两种格式
df = df.withColumn("ts", F.to_timestamp(F.col("PurchaseDatetime"), ["dd/MM/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm"]))

# 拆分日期和时间列
df = df.withColumn("PurchaseDate", F.date_format(F.col("ts"), "dd-MM-yyyy")) \
       .withColumn("PurchaseTime", F.date_format(F.col("ts"), "HH:mm:ss")) \
       .drop("ts")

方法2:判断格式后分别解析(兼容低版本Spark)

from pyspark.sql import functions as F

# 判断字符串是否包含秒部分,分别解析为时间戳
df = df.withColumn("ts", 
                   F.when(F.col("PurchaseDatetime").contains(":"),
                          F.to_timestamp(F.col("PurchaseDatetime"), "dd/MM/yyyy HH:mm:ss"))
                    .otherwise(F.to_timestamp(F.col("PurchaseDatetime"), "dd/MM/yyyy HH:mm")))

# 拆分日期和时间列
df = df.withColumn("PurchaseDate", F.date_format(F.col("ts"), "dd-MM-yyyy")) \
       .withColumn("PurchaseTime", F.date_format(F.col("ts"), "HH:mm:ss")) \
       .drop("ts")

处理后缺失的秒部分会自动补为00,日期和时间列可正常生成,符合预期输出。


内容的提问来源于stack exchange,提问作者Reza7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:01:02