Spark SQL中str_to_date替代方案:批量转换日期列遇问题求助
解决Spark SQL日期字符串转换问题
我来帮你搞定这个Spark SQL的日期转换坑,你的问题核心出在日期格式符的大小写误用上,咱们一步步拆解解决:
为什么之前的转换会出错?
Spark SQL里的日期格式符是严格区分大小写的,你踩了两个常见的格式符误区:
- 小写的
mm代表的是分钟,不是月份!月份必须用大写的MM——这就是你换成YYYY-mm-dd后得到错误日期(2017-12-31)的核心原因:字符串里的"01"被当成了分钟,日期解析失败后默认回退到了UNIX纪元起始附近的日期。 - 虽然
YYYY也能识别年份,但规范的年份格式符是小写的yyyy,建议统一使用,避免特殊场景下的解析异常。
正确的转换写法(年-月-日格式)
其实Spark SQL的TO_DATE函数本身就支持直接指定输入格式,不用绕UNIX_TIMESTAMP,写法更简洁可靠:
SELECT name, enroll_DATE, TO_DATE(enroll_DATE, 'yyyy-MM-dd') AS converted_ED FROM data
执行后你会得到符合预期的结果:
+----+-----------+-----------+ |name|enroll_DATE|converted_ED| +----+-----------+-----------+ | a| 2018-01-20| 2018-01-20| | b| 2018-01-21| 2018-01-21| | c| 2018-01-22| 2018-01-22| +----+-----------+-----------+
查看表结构的话,converted_ED会是标准的date类型。
支持年-日-月(%Y-%d-%m)格式的转换
如果你的日期字符串是年-日-月的格式(比如2018-20-01),只需要把格式符对应改成yyyy-dd-MM即可:
SELECT name, enroll_DATE, TO_DATE(enroll_DATE, 'yyyy-dd-MM') AS converted_ED FROM data
处理同一列混合两种格式的情况
如果你的数据里同时存在年-月-日和年-日-月两种格式,可以用CASE WHEN做逻辑判断来分别转换:
SELECT name, enroll_DATE, CASE -- 判断最后一段是否为合法月份(≤12),是的话按年-月-日解析 WHEN CAST(SUBSTRING_INDEX(enroll_DATE, '-', -1) AS INT) <= 12 THEN TO_DATE(enroll_DATE, 'yyyy-MM-dd') -- 否则按年-日-月解析 ELSE TO_DATE(enroll_DATE, 'yyyy-dd-MM') END AS converted_ED FROM data
这个逻辑能覆盖大部分场景,如果有极端情况(比如日期是2018-12-12,两种格式都合法),你可能需要结合业务规则补充额外判断条件。
内容的提问来源于stack exchange,提问作者Satya
相关产品推荐
相关产品推荐

