PySpark中基于4月起始财年从日期列计算年度周数
嘿,这个问题我刚好处理过!Spark默认的weekofyear确实是按自然年(1月1日为起始)计算周数的,要改成以4月1日为财年起始的计算逻辑,我给你两种靠谱的方案,优先推荐第一种,因为能避开边界日期的坑:
方法一:基于财年起始日计算天数差(稳妥无边界问题)
这个方法的核心逻辑是先确定每个日期对应的财年起始日,再通过日期差计算周数,完全贴合财年的时间范围:
- 确定财年起始日:如果日期的月份≥4,财年起始就是当年的4月1日;如果月份<4,财年起始就是前一年的4月1日。
- 计算财年周数:用当前日期减去财年起始日的天数差,除以7取整后加1(因为第1天属于第1周)。
代码实现:
from pyspark.sql import functions as F # 第一步:计算每个日期对应的财年起始日 df = df.withColumn( "fy_start", F.when( F.month("date") >= 4, # 生成当年4月1日:先截断到当年年初,再格式化为4月1日并转成日期类型 F.to_date(F.date_format(F.date_trunc("year", "date"), "yyyy-04-01")) ).otherwise( # 生成前一年4月1日:截断到当年年初后减1年,再格式化为4月1日 F.to_date(F.date_format(F.add_months(F.date_trunc("year", "date"), -12), "yyyy-04-01")) ) ) # 第二步:计算财年周数 df = df.withColumn( "week", # 天数差除以7取整,加1得到对应的财年周数 F.floor(F.datediff("date", "fy_start") / 7) + 1 ) # 可选:如果不需要中间列fy_start,可以删掉它 df = df.drop("fy_start")
用你的示例数据验证一下:
2018-08-12:财年起始是2018-04-01,天数差133天,133÷7=19,加1得202019-01-23:财年起始是2018-04-01,天数差297天,297÷7≈42.43,取整42加1得432019-04-03:财年起始是2019-04-01,天数差2天,取整0加1得1
方法二:日期偏移适配weekofyear(简洁但有边界局限)
如果你的业务场景可以接受ISO周的边界处理(比如财年末尾的日期可能被归为下财年第1周),可以用更简洁的方式:把日期减去3个月,这样4月1日就对应自然年的1月1日,直接用weekofyear计算即可:
from pyspark.sql import functions as F df = df.withColumn( "week", F.weekofyear(F.add_months("date", -3)) )
⚠️ 注意:比如2020-03-31(属于2019财年最后一天),减去3个月是2019-12-31,weekofyear会返回1(因为这一天属于2020年的第1周),但实际它应该是2019财年的最后一周,这种边界情况需要额外调整,所以方法一更稳妥。
内容的提问来源于stack exchange,提问作者Pallavi Verma
相关产品推荐
相关产品推荐

