Spark 2.2中微秒时间字符串转Timestamp返回null问题排查
问题根源
在Spark 2.2版本中,to_timestamp函数底层依赖Java的SimpleDateFormat类,而这个类的日期格式规则里,S代表的是毫秒(0-999),并不支持SSSSSS这种六位微秒的格式。当你传入008288这样的六位数字时,它会把整个数值当作毫秒数来处理——也就是8288毫秒,等于8.288秒,这会和原字符串中的秒数00产生冲突,导致解析失败,最终返回null。
另外还有个细节需要注意:你用的是hh(12小时制),如果你的时间包含下午时段(比如13点及以后),这个格式也会解析出错,但这次返回null的核心原因还是微秒格式不兼容。
解决方案
根据你的精度需求,这里提供两种可行的方法:
方法一:截断微秒到毫秒(精度允许的情况下)
如果可以接受舍弃后三位微秒,只保留毫秒精度,我们可以先截取字符串的前19位(到秒)加上微秒的前三位,再用支持的SSS格式解析:
from pyspark.sql.functions import substring, concat, to_timestamp # 先处理字符串,把微秒截断为毫秒 df = df.withColumn( "formatted_time", concat(substring("my_time", 1, 19), substring("my_time", 21, 3)) ) # 再转换为timestamp df = df.withColumn( "my_time_timestamp", to_timestamp("formatted_time", "yyyyMMdd-hh:mm:ss.SSS") )
方法二:保留完整微秒精度
如果需要保留全部六位微秒的精度,我们可以通过「秒级时间戳 + 微秒小数部分」的方式来构造timestamp:
from pyspark.sql.functions import unix_timestamp, substring, col, cast # 提取秒级时间戳 df = df.withColumn( "second_timestamp", unix_timestamp(substring("my_time", 1, 19), "yyyyMMdd-hh:mm:ss") ) # 提取微秒部分并转换为秒的小数 df = df.withColumn( "microsecond_decimal", substring("my_time", 21, 6).cast("double") / 1000000 ) # 合并后转换为timestamp类型 df = df.withColumn( "my_time_timestamp", (col("second_timestamp") + col("microsecond_decimal")).cast("timestamp") )
最后提醒下,如果你的时间是24小时制的,记得把格式里的hh换成HH,避免上午/下午的解析错误。
内容的提问来源于stack exchange,提问作者SecretAgent
相关产品推荐
相关产品推荐

