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

PySpark多日期格式转换失败:单数字日/月解析异常求助

解决PySpark多格式日期解析异常问题

问题根源

Spark 3.0及以上版本默认启用了新的日期时间解析器(基于Java 8+的java.time API),相比旧版的SimpleDateFormat,新解析器规则更严格:

  • 格式中的dd/MM要求必须是两位数字,单数字的日/月(如2018-12-1里的1、24/7/2006里的7)会直接匹配失败
  • 默认不允许宽松解析,一旦匹配失败就抛出SparkUpgradeException,而非返回null让coalesce继续尝试其他格式

解决方案

方案1:补充兼容单数字的日期格式 + 启用宽松解析模式

修改自定义日期转换函数,补充覆盖单数字日/月的格式,并给每个to_date调用指定PERMISSIVE模式(解析失败时返回null,而非抛出异常):

from pyspark.sql.functions import coalesce, to_date

def custom_to_date(col):
    # 补充单数字日/月对应的格式,覆盖所有可能的情况
    formats = (
        "MM/dd/yyyy", "MM/d/yyyy", "M/dd/yyyy", "M/d/yyyy",
        "yyyy-MM-dd", "yyyy-M-d", "yyyy-MM-d", "yyyy-M-dd",
        "dd/MM/yyyy", "dd/M/yyyy", "d/MM/yyyy", "d/M/yyyy",
        "MM/yy"
    )
    # 启用PERMISSIVE模式,解析失败返回null,让coalesce继续尝试其他格式
    return coalesce(*[to_date(col, f, {"mode": "PERMISSIVE"}) for f in formats])

# 测试数据
df = spark.createDataFrame([(1, "01/22/2010"), (2, "2018-12-1"),(3,"24/7/2006")], ("id", "dt"))
df.withColumn("pdt", custom_to_date("dt")).show()

运行后会正确解析所有格式的日期,仅完全无法匹配的记录会返回null。

方案2:回退到旧版解析器(全局配置)

如果不想修改代码中的格式列表,可以通过Spark配置切换回旧版的宽松解析规则:

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("DateParsingDemo") \
    # 启用旧版时间解析策略,兼容Spark 2.x的宽松匹配
    .config("spark.sql.legacy.timeParserPolicy", "LEGACY") \
    .getOrCreate()

# 原来的自定义函数无需修改即可正常运行
def custom_to_date(col):
    formats = ("MM/dd/yyyy", "yyyy-MM-dd", "dd/MM/yyyy", "MM/yy","dd/M/yyyy")
    return coalesce(*[to_date(col, f) for f in formats])

df = spark.createDataFrame([(1, "01/22/2010"), (2, "2018-12-1"),(3,"24/7/2006")], ("id", "dt"))
df.withColumn("pdt", custom_to_date("dt")).show()

这个方案会让Spark使用旧的SimpleDateFormat解析日期,自动兼容单数字日/月的情况,但旧解析器存在部分年份解析歧义等已知问题,需要根据业务场景选择。

内容的提问来源于stack exchange,提问作者SK ASIF ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:22:45