Spark字符串转日期失败求助:解析'5-17-2015'报错
解决Spark中日期转换与排序的问题
我来帮你搞定这个日期转换的坑!首先咱们得弄明白你之前踩的两个核心问题:
为什么第一次转换会出现NULL?
你一开始用的格式串是'MM-dd-yyyy',但你的原始日期格式是月/日/两位年(比如1/1/15)——不仅分隔符是/不是-,年份也只有两位,和你指定的yyyy四位年完全不匹配。再加上Spark 3.0之后默认使用的日期解析器对格式匹配要求更严格,所以直接返回NULL是必然的结果。
为什么排序会触发Py4JJavaError?
你用regexp_replace把格式改成了1-1-2015,但这时候这个列还是字符串类型,不是真正的Date类型。Spark 3.0之后的优化逻辑会在排序时尝试自动推断类型,当它把这个字符串当成日期解析时,默认的日期格式是yyyy-MM-dd,和5-17-2015完全不匹配,所以就抛出了解析错误。
正确的解决方案分两种情况:
情况1:直接从原始日期列转换(推荐)
不需要绕unix_timestamp,直接用to_date函数指定和原始格式完全匹配的格式串'M/d/yy':
from pyspark.sql.functions import col, to_date # 直接解析原始日期字符串为Date类型 data = data.withColumn('date', to_date(col('date'), 'M/d/yy')) # 现在可以正常排序 data.orderBy('date').show()
这里的M和d对应无前置零的月/日,yy对应两位年份,Spark会自动把15转换成2015(默认规则是两位年在00-99范围内对应2000-2099,如果需要处理19xx的年份,可以后续再调整)。
情况2:如果你已经用regexp_replace处理过字符串
先把处理后的字符串转换成真正的Date类型,再排序:
from pyspark.sql.functions import col, to_date, regexp_replace # 先替换分隔符并补全年份(假设原始年份是两位) data = data.withColumn('date_str', regexp_replace(col('date'), r'(\d+)/(\d+)/(\d+)', r'$1-$2-20$3')) # 将字符串转换为Date类型,指定匹配的格式串 data = data.withColumn('date', to_date(col('date_str'), 'M-d-yyyy')).drop('date_str') # 现在排序就不会报错了 data.orderBy('date').show()
关键提醒:
Spark 3.0之后的日期解析器(基于Java的DateTimeFormatter)比旧版本严格很多,格式串必须和输入字符串的格式完全对应:
- 无前置零的月/日用
M/d,有前置零的用MM/dd - 分隔符要和原始字符串一致(
/或-) - 两位年用
yy,四位年用yyyy
内容的提问来源于stack exchange,提问作者Somasundharam Sampath
相关产品推荐
相关产品推荐

