Spark DataFrame中to_timestamp转换含周日期串返回NULL求助
Spark日期转时间戳返回NULL的排查与解决
问题根源
你遇到的NULL问题主要出在两个地方:
- 格式符号错用:你用的
SSSSSS不符合SimpleDateFormat规则——S只代表毫秒(最多3位),而你的字段里是6位微秒,LEGACY模式下to_timestamp没法直接识别这部分。 - 区域不匹配:
Thu(星期缩写)、Mar(月份缩写)是英文格式,如果你的Spark集群默认JVM区域不是英文,解析时会因为识别不了这些缩写直接返回NULL。
解决办法
方法1:拆分处理微秒+指定英文区域
这种方法能完整保留微秒精度,步骤如下:
import org.apache.spark.sql.functions._ import java.util.Locale val processedData = data // 拆分日期字符串为秒级部分、微秒部分、时区部分 .withColumn("sec_part", substring(col("timestamp_str"), 1, 20)) .withColumn("microsec", substring(col("timestamp_str"), 22, 6)) .withColumn("timezone", substring(col("timestamp_str"), 29, 5)) // 先解析出秒级时间戳 .withColumn("ts_sec", unix_timestamp(concat(col("sec_part"), col("timezone")), "EEE, dd MMM yyyy HH:mm:ss Z").cast("long")) // 把微秒转成秒的小数部分,加到时间戳上 .withColumn("timestamp_res", timestamp_seconds(col("ts_sec")) + col("microsec").cast("double") / 1000000) // 清理临时字段 .drop("sec_part", "microsec", "timezone", "ts_sec")
方法2:直接修正格式+指定区域(微秒会截断)
如果不需要完整微秒精度,或者可以接受截断后三位,直接给to_timestamp指定英文区域,同时保留原格式:
import org.apache.spark.sql.functions._ import java.util.Locale val processedData = data.withColumn( "timestamp_res", to_timestamp( col("timestamp_str"), "EEE, dd MMM yyyy HH:mm:ss SSSSSS Z", Locale.ENGLISH ) )
注意:LEGACY模式下,超过3位的S会被截断,也就是说237111会被当成237毫秒,后面的111会丢失。
额外提醒:确认LEGACY模式生效
一定要确保你的Spark配置真的生效,代码里可以加一行:
spark.conf.set("spark.sql.legacy.timeParserPolicy", "LEGACY")
内容的提问来源于stack exchange,提问作者boozy
相关产品推荐
相关产品推荐

