Spark 3.3.2无毫秒点的时间戳字符串转换失败求助
Spark 3.3.2 转换无小数点的时间戳字符串为带毫秒的时间格式
问题场景
在Spark 3.3.2中,尝试将格式为2023061218154258的时间戳字符串转换为2023-06-12 18:15:42.58格式的时间戳时,使用to_timestamp指定yyyyMMddHHmmssSS格式返回null;指定yyyyMMddHHmmss.SS仅能转换带小数点的字符串20230612181542.58,无法处理无小数点的输入。
核心原因
Spark的to_timestamp基于Java的DateTimeFormatter实现,对于无小数点的毫秒部分,SS格式符会被解析为秒的延伸(而非独立的毫秒),导致数值超出合法范围(秒数不能超过60),最终解析失败返回null。
解决方法:统一预处理字符串格式
通过正则表达式将无小数点的时间戳字符串转换为带小数点的格式,再用yyyyMMddHHmmss.SS解析,同时兼容原有带小数点的输入。
代码实现
from pyspark.sql.functions import * spark.conf.set("spark.sql.legacy.timeParserPolicy", "CORRECTED") # 创建测试数据框 df = spark.createDataFrame( data=[("1", "2023061218154258"), ("2", "20230612181542.58")], schema=["id", "input_timestamp"] ) # 预处理字符串并转换时间戳 df_processed = df.withColumn( # 用正则表达式给最后两位毫秒前添加小数点 "formatted_str", regexp_replace("input_timestamp", r"(\d{14})(\d{2})$", r"\1.\2") ).withColumn( "timestamp", to_timestamp("formatted_str", "yyyyMMddHHmmss.SS") ) # 查看结果 df_processed.show(truncate=False)
输出结果
+---+-----------------+-----------------------+----------------------+ |id |input_timestamp |formatted_str |timestamp | +---+-----------------+-----------------------+----------------------+ |1 |2023061218154258 |20230612181542.58 |2023-06-12 18:15:42.58| |2 |20230612181542.58|20230612181542.58 |2023-06-12 18:15:42.58| +---+-----------------+-----------------------+----------------------+
替代方法:拆分秒和毫秒部分
如果不想使用正则表达式,也可以通过截取字符串拆分秒和毫秒部分,再合并为时间戳:
df_processed = df.withColumn( # 截取前14位转为秒级时间戳 "sec_timestamp", unix_timestamp(substring("input_timestamp", 1, 14), "yyyyMMddHHmmss") ).withColumn( # 去除小数点后截取最后两位,转为毫秒值(除以100转为秒的小数部分) "millis", substring(regexp_replace("input_timestamp", r"\.", ""), 15, 2).cast("int") / 100 ).withColumn( # 合并为最终时间戳 "timestamp", to_timestamp("sec_timestamp" + "millis") ) df_processed.show(truncate=False)
内容的提问来源于stack exchange,提问作者Bas van den Berg
相关产品推荐
相关产品推荐

