为何Spark SQL的unix_timestamp解析时间会相差12小时?
Spark SQL
unix_timestamp解析12小时制时间的异常问题 问题描述
在Spark 2.1.1版本中,使用unix_timestamp解析12小时制格式的时间时会出现逻辑错误:明明时间更晚的字符串,解析出的时间戳反而更小。
来看这两个实际例子:
-- 解析中午12:03:56,却返回对应凌晨00:03:56的时间戳1499040236 select unix_timestamp("2017-07-03T12:03:56", "yyyy-MM-dd'T'hh:mm:ss") -- 解析凌晨00:18:31,返回正确的时间戳1499041111 select unix_timestamp("2017-07-03T00:18:31", "yyyy-MM-dd'T'hh:mm:ss")
很明显第一个时间(中午12点)比第二个(凌晨0点18分)晚,但解析出的时间戳数值却更小,完全不符合逻辑。
用R语言验证正确结果
我们可以用R语言计算正确的时间戳,确认Spark的解析错误:
手动计算验证
通过时间单位累加计算目标时间的时间戳:
# 定义时间单位常量 one_day = 60 * 60 * 24 one_year = 365 * one_day one_year_leap = 366 * one_day one_quad = 3 * one_year + one_year_leap # 计算2017-07-03 00:18:31的时间戳 11 * one_quad + 2 * one_year + one_year_leap + (31 + 28 + 31 + 30 + 31 + 30) * one_day + 2 * one_day + 18 * 60 + 31 # 输出结果:[1] 1499041111(和Spark返回的第二个结果一致,说明这个解析是正确的)
直接用POSIXct工具验证
对于第一个时间(2017-07-03 12:03:56),用R的as.POSIXct直接转换:
as.integer(as.POSIXct('2017-07-03 12:03:56', tz = 'UTC')) # 输出结果:[1] 1499083436(这才是中午12点对应的正确时间戳)
额外测试确认问题点
- 测试凌晨00:03:56的解析:
select unix_timestamp("2017-07-03T00:03:56", "yyyy-MM-dd'T'hh:mm:ss") -- 正确返回1499040236,说明Spark对00开头的12小时制时间解析正常,但把12开头的中午时间错误识别成了凌晨
- 将时间字符串中的
T替换为空格,错误依然存在,说明分隔符不影响这个bug的触发。
版本与修复情况
这个异常是Spark 2.1.1版本特有的bug,后续的Spark开发版本已经修复了这个12小时制时间解析的问题。
内容的提问来源于stack exchange,提问作者MichaelChirico
相关产品推荐
相关产品推荐

