You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark中dd-MMM-YY格式日期字符串转Timestamp失败求助

日期转换错误的原因分析与修复方案

嘿,我帮你拆解了下你遇到的日期转Timestamp出错的问题,主要有几个核心坑点,还有对应的解决办法:

最可能的问题:格式匹配与年份解析偏差

你的日期格式是1-Jan-14(单数字日+英文月份缩写+两位年份),你用的d-MMM-yy格式看起来没问题,但其实藏着两个容易踩的坑:

  • 月份缩写的语言依赖:MMM这个格式符要求Spark运行环境的默认语言是英文,如果你的本地/集群环境是其他语言(比如中文),就识别不了Jan这种英文月份缩写,直接返回null。
  • 两位年份的解析逻辑:yy格式默认会把14解析成1914而不是2014,而unix时间戳是从1970年开始计算的,1914年早于这个时间点,转成Timestamp自然会得到错误值甚至null。

次要问题:unix_timestamp的局限性

unix_timestamp返回的是从1970-01-01到目标日期的秒数,本身是个长整型。如果解析出的年份在1970之前,这个值会是负数,而Timestamp类型基于unix时间戳,没法表示1970年之前的时间,这就直接导致转换失败。


修复方案:用更可靠的to_timestamp函数

Spark 2.0之后推出的to_timestamp函数比unix_timestamp更友好,直接支持日期转Timestamp,还能指定语言环境和时区,完美解决上面的问题:

import org.apache.spark.sql.functions.to_timestamp

val finalDf: DataFrame = priceDF
 .withColumn("Price", priceDF("ClosePrice").cast(DoubleType))
 // 核心修复:用to_timestamp,指定格式,同时加上英文locale避免语言识别问题
 .withColumn("TimeStamp", to_timestamp($"Date", "d-MMM-yy", "en_US"))
 .drop("Date").drop("ClosePrice")
 .sort("TimeStamp")

如果你的Spark版本比较旧,必须用unix_timestamp,那得手动调整年份:

import org.apache.spark.sql.functions.{unix_timestamp, lit, when}

val finalDf: DataFrame = priceDF
 .withColumn("Price", priceDF("ClosePrice").cast(DoubleType))
 .withColumn("unixTime", unix_timestamp($"Date", "d-MMM-yy"))
 // 把19xx的日期调整为20xx:如果unixTime是负数(早于1970),加上100年的秒数
 .withColumn("adjustedUnixTime", when($"unixTime" < 0, $"unixTime" + lit(3153600000L)).otherwise($"unixTime"))
 .withColumn("TimeStamp", $"adjustedUnixTime".cast(TimestampType))
 .drop("Date", "ClosePrice", "unixTime", "adjustedUnixTime")
 .sort("TimeStamp")

额外提醒

  • 先确认你的CSV里所有日期格式都是统一的d-MMM-yy,要是有混合格式(比如有的是01-Jan-14),得先做数据清洗。
  • 最好在Spark配置里指定时区,避免时区差异导致的时间偏差:
    sparkConf.set("spark.sql.session.timeZone", "Asia/Kolkata") // 换成你实际用的时区,比如UTC
    

内容的提问来源于stack exchange,提问作者Shashi Shankar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:18:04