PySpark字符串转日期年份映射问题:如何修正两位年份转换结果
解决PySpark中两位年份解析的世纪映射问题
你的问题在于使用to_date解析dd-MMM-yy格式的日期时,PySpark依赖的Java SimpleDateFormat默认的两位年份映射规则不符合业务预期——默认规则会基于当前年份的 pivot 值(通常为当前年份减80)自动分配世纪,导致09-Aug-96被解析为2096-08-09而非期望的1996-08-09。
以下是两种精准控制两位年份映射的解决方案:
方案一:手动拼接年份字符串后解析(固定规则)
直接指定两位年份对应的世纪区间,比如约定:
- 00-23 → 2000-2023
- 24-99 → 1924-1999
from pyspark.sql import SparkSession from pyspark.sql.functions import to_date, substring, lit, concat, when, date_format # 初始化SparkSession spark = SparkSession.builder.getOrCreate() # 示例数据 data = [("09-Aug-96",), ("05-Sep-23",)] df = spark.createDataFrame(data, ["date_string"]) # 自定义两位年份映射逻辑 df = df.withColumn( "two_digit_year", substring("date_string", -2, 2).cast("int") ).withColumn( "full_date_str", concat( substring("date_string", 1, 6), # 截取"dd-MMM-"部分 when("two_digit_year" <= 23, lit("20")).otherwise(lit("19")), # 选择世纪前缀 substring("date_string", -2, 2) # 拼接两位年份 ) ).withColumn( "date", to_date("full_date_str", "dd-MMM-yyyy") # 按完整格式解析为日期类型 ).withColumn( "formatted_date", date_format("date", "dd-MM-yyyy") # 格式化为目标字符串 ) # 查看结果 df.select("date_string", "date", "formatted_date").show(truncate=False)
执行结果:
+-----------+----------+--------------+ |date_string|date |formatted_date| +-----------+----------+--------------+ |09-Aug-96 |1996-08-09|09-08-1996 | |05-Sep-23 |2023-09-05|05-09-2023 | +-----------+----------+--------------+
方案二:解析后动态调整年份(适配当前时间)
如果需要根据当前年份动态调整映射规则,比如解析后的年份超过当前年份+20时,自动减去100年:
from pyspark.sql import SparkSession from pyspark.sql.functions import to_date, year, current_date, add_months, date_format, when spark = SparkSession.builder.getOrCreate() data = [("09-Aug-96",), ("05-Sep-23",)] df = spark.createDataFrame(data, ["date_string"]) # 先按默认规则解析日期 df = df.withColumn("raw_date", to_date("date_string", "dd-MMM-yy")) # 动态调整年份:若解析年份超过当前年份+20,减去100年 current_year = year(current_date()) df = df.withColumn( "adjusted_date", when(year("raw_date") > current_year + 20, add_months("raw_date", -1200)).otherwise("raw_date") ).withColumn( "formatted_date", date_format("adjusted_date", "dd-MM-yyyy") ) df.select("date_string", "adjusted_date", "formatted_date").show(truncate=False)
你可以根据业务需求修改阈值(比如把current_year + 20改为固定年份2050),或者调整映射区间的分界值(比如将方案一中的23改为30,覆盖更多20xx年份)。
内容的提问来源于stack exchange,提问作者Ramineni Ravi Teja
相关产品推荐
相关产品推荐

