Spark(Scala)中timestamp转字符串不丢失毫秒的实现方法咨询
问题根因
Spark的to_timestamp函数在解析时间字符串时,如果你传入的格式字符串fmt未包含毫秒占位符SSS,会默认丢弃毫秒部分;哪怕后续调用date_format时指定了毫秒格式,也无法找回被截断的精度。
可行简便方案
方案1(推荐,适配Spark 3.0+)
利用Spark 3.0及以上版本支持的可选格式段语法,给你预设的所有fmt格式加上可选的毫秒匹配段,用[]包裹即可:
- 原格式示例:
yyyy-MM-dd HH:mm:ss - 修改后格式:
yyyy-MM-dd HH:mm:ss[.SSS]
这种写法可以同时适配带毫秒和不带毫秒的时间字符串,存在毫秒时会自动保留精度,不存在时也不会报错。
同时需要注意,你的outputFormat参数必须包含SSS占位符,才能让date_format输出毫秒部分,示例:outputFormat = "yyyy-MM-dd HH:mm:ss.SSS"
修改后的代码示例:
when(to_date($"timestamp", fmt).isNotNull, date_format(to_timestamp($"timestamp", fmt), outputFormat))
方案2(兼容Spark 2.x)
如果使用的是不支持可选格式段的低版本Spark,可以在匹配格式前先判断时间字符串是否包含小数点:
- 包含小数点的字符串使用带
SSS的格式解析 - 不包含小数点的字符串使用普通格式解析
只需要在原有格式匹配逻辑前加一层简单的字符串判断即可,不需要大幅修改原有逻辑。
注意事项
- 如果源数据的毫秒精度超过3位(比如存在微秒),可以按需增加
S的数量,比如.SSSSSS可保留6位微秒精度 - 不同时间分隔符的格式都可以用同样的逻辑加可选毫秒段,比如
yyyy/MM/dd HH:mm:ss[.SSS]、dd-MM-yyyy HH:mm:ss[.SSS]等都适用
内容的提问来源于stack exchange,提问作者Silva_PT_SCP
相关产品推荐
相关产品推荐

