Spark中Excel读取的整数日期值如何正确转换为时间戳
Excel整数日期值转Spark时间戳的正确方案
转换偏差的核心原因
两者的时间编码规则完全错位,没有对齐逻辑:
- Excel的日期编码规则:以1900-01-01为逻辑起点,每过1天整数值加1,且内置了1900年闰年兼容bug(误将不存在的1900-02-29算作有效日期),整数值本身仅代表自然日偏移量,不携带时区、时间起点信息
- Spark默认的整数转时间戳逻辑:对整数字段直接执行
cast(xxx as timestamp)时,会将整数解析为自1970-01-01 00:00:00 UTC起累计的秒数,完全沿用Unix时间的计算规则。
对应到你遇到的场景:数值43517直接cast时,Spark会计算从1970年元旦开始累计43517秒的偏移,合计约12小时,结合本地时区差就会算出1970-01-01 09:06左右的结果,和预期的2019年日期偏差极大。
可直接落地的转换实现
适配绝大多数Windows端Excel默认的1900日期系统,核心是对齐和Excel规则一致的基准时间:
经验证,取
1899-12-30作为转换的基准时间,可完全兼容Excel的1900年闰年bug,无需手动计算2天的偏移量
转换的核心公式为:目标时间戳 = 1899-12-30 00:00:00 + (Excel整数值 * 86400秒)(86400为单天的总秒数)
可以直接替换你原有selectExpr的逻辑,适配整数、带小数的Excel日期值:
val dfConverted = df.selectExpr( "timestamp('1899-12-30') + make_interval(seconds => date * 86400) as date" )
如果习惯用DataFrame原生API,等价写法为:
import org.apache.spark.sql.functions._ val dfConverted = df.withColumn( "date", lit("1899-12-30").cast("timestamp") + col("date") * expr("INTERVAL 1 DAY") )
特殊场景适配
- 若处理的是Mac端老版本Excel的1904日期系统(逻辑起点为1904-01-01),仅需将代码中的基准日期从
1899-12-30替换为1904-01-01,其余逻辑完全不变 - 若Excel日期值带有小数部分(比如43517.5对应2019-04-16 12:00:00),上述公式可直接兼容,无需额外调整。
内容的提问来源于stack exchange,提问作者Felipe Troncoso Ortiz
相关产品推荐
相关产品推荐

