如何在PySpark中使用to_timestamp函数转换含6位毫秒的时间戳
解决Spark中6位微秒时间戳字符串转Timestamp返回Null的问题
我来帮你搞定这个时间戳转换的坑!你遇到的问题核心在于Spark对时间戳格式解析的精度限制,以及不同版本Spark底层解析逻辑的差异。
为什么你的代码会返回Null?
你用"yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"作为格式字符串时,在Spark 2.x版本中,底层依赖的SimpleDateFormat只支持最多3位毫秒(SSS),超过3位的SSSSSS会被判定为无效毫秒值(比如926866毫秒远超出0-999的合理范围),直接导致解析失败返回Null。而Spark 3.x虽然切换到了支持微秒的DateTimeFormatter,但硬编码'Z'作为字面量的方式,有时会和时区解析逻辑冲突,同样引发解析异常。
解决方案分两种情况:
方案1:最简单的方式——让Spark自动解析(推荐)
Spark 2.2+版本已经支持自动识别标准ISO8601格式的时间戳(包括带Z的UTC时间和6位微秒),你完全不需要指定格式字符串,直接调用to_timestamp即可:
import pyspark.sql.functions as F from pyspark.sql.functions import col df = spark.createDataFrame([("2022-07-28T10:38:50.926866Z",)],['date_str']) df.withColumn("ts1", F.to_timestamp(col('date_str'))).show(truncate=False)
执行后会得到正确的Timestamp结果,Spark会自动处理UTC时区和微秒精度。
方案2:指定格式字符串(针对特殊场景)
如果你必须明确指定格式,分Spark版本处理:
- Spark 3.x版本:使用
XXX表示时区偏移(Z对应UTC+00:00),同时用SSSSSS表示微秒:
df.withColumn("ts1", F.to_timestamp(col('date_str'), "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX")).show(truncate=False)
- Spark 2.x版本:先截取字符串到毫秒位(保留前23个字符),再用3位毫秒的格式解析:
df.withColumn("ts1", F.to_timestamp(F.substring(col('date_str'), 1, 23), "yyyy-MM-dd'T'HH:mm:ss.SSS")).show(truncate=False)
验证结果
不管用哪种方案,你都会得到类似这样的输出:
+-----------------------------+-----------------------+ |date_str |ts1 | +-----------------------------+-----------------------+ |2022-07-28T10:38:50.926866Z |2022-07-28 10:38:50.926| +-----------------------------+-----------------------+
注意:Spark的Timestamp类型在显示时默认只展示到毫秒,但内部会保留微秒精度(你可以通过cast("string")查看完整精度)。
内容的提问来源于stack exchange,提问作者paytur
相关产品推荐
相关产品推荐

