Spark Scala DataFrame按周数取周日周末日期 第53周返回null如何解决
问题根因
- 你当前用
to_date(col("year_week_number"), "w/yyyy")解析53/2020返回null,核心是两点:- Spark默认周起始日为周日,和你要求的周一规则不匹配,导致默认规则下2020年的周数上限为52,无法解析第53周
- 原有闰年判断后加7/14天的逻辑和周数计算无关,属于冗余错误逻辑,周数是否存在第53周和闰年无直接关联,由当年1月1日的星期属性决定
- 你需要的2020年第53周(周一到周日)的日期范围是2020-12-28至2021-01-03,周末为2021-01-03,符合业务预期。
解决方案
第一步:配置周起始规则
首先设置Spark SQL全局参数,指定周起始日为周一,和你的业务规则对齐:
// 参数值1代表周一,7代表周日(Spark默认值) spark.conf.set("spark.sql.weekStart", "1")
第二步:修正日期计算逻辑
删除冗余的闰年判断逻辑,解析周数后加6天即可得到当周周日(周一是第1天,加6天为周日):
case class Data(id:Int,weekNumber:String) var stgDF = Seq(Data(100,"53/2020")).toDF() val weekNumber = "53/2020" stgDF = stgDF .withColumn("year_week_number", lit(weekNumber)) .withColumn("dsupp_trans_dt", date_add(to_date(col("year_week_number"), "w/yyyy"), 6)) stgDF.show(false)
输出验证
调整后输出结果如下,符合预期:
+---+----------+----------------+--------------+ |id |weekNumber|year_week_number|dsupp_trans_dt| +---+----------+----------------+--------------+ |100|53/2020 |53/2020 |2021-01-03 | +---+----------+----------------+--------------+
用52/2020测试也会得到你之前的正确结果2020-12-27,兼容原有正常场景。
Spark 2.x兼容方案
如果你使用的是没有spark.sql.weekStart参数的Spark 2.x版本,可以用自定义UDF实现周计算,不需要依赖全局配置:
import java.time.LocalDate import java.time.temporal.WeekFields import java.util.Locale val getWeekendUdf = udf((weekYearStr: String) => { val Array(weekNum, year) = weekYearStr.split("/").map(_.toInt) val weekFields = WeekFields.of(Locale.CHINA) // 周起始为周一的区域规则 val firstDayOfWeek = LocalDate.of(year, 1, 1) .`with`(weekFields.weekOfWeekBasedYear(), weekNum) .`with`(weekFields.dayOfWeek(), 1) firstDayOfWeek.plusDays(6).toString }) // 调用UDF计算 stgDF = stgDF.withColumn("dsupp_trans_dt", to_date(getWeekendUdf(col("year_week_number"))))
内容的提问来源于stack exchange,提问作者Surender Raja
相关产品推荐
相关产品推荐

