You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成当前日期前n个月份的月末日期列表(不含当月)

生成当前日期前N个月份的月末日期列表(不含当月)

需求说明

需要生成当前日期之前n个月份的月末日期列表,不包含当月的月末日期。例如,若当前为2022年12月,过去4个月的月末日期应为:

daterange = ['2022-08-31','2022-09-30','2022-10-31','2022-11-30']

尝试过的方法及问题

方法1:Python自定义函数

编写了如下函数,用固定30天近似计算:

def last_n_month_end(n_months):
    """
    Returns a list of the last n month end dates
    """
    return [datetime.date.today().replace(day=1) - datetime.timedelta(days=1) - datetime.timedelta(days=30*i) for i in range(n_months)]
  • 问题:仅在每月均为30天时部分有效,无法适配不同月份的天数差异;
  • 在Databricks PySpark环境中运行时抛出错误:AttributeError: 'method_descriptor' object has no attribute 'today'(因Databricks中datetime模块的使用方式差异导致)。

方法2:Stack Overflow方案

尝试了以下代码,但未得到正确结果:

def previous_month_ends(date, months):
  year, month, day = [int(x) for x in date.split('-')]
  d = datetime.date(year, month, day)
  t = datetime.timedelta(1)
  s = datetime.date(year, month, 1)
  return [(x - t).strftime('%Y-%m-%d')
          for m in range(months - 1, -1, -1)
          for x in (datetime.date(s.year, s.month - m, s.day) if s.month > m else \
                    datetime.date(s.year - 1, s.month - (m - 12), s.day),)]

方法3:PySpark代码

尝试用PySpark的sequence函数生成,但生成过去3个月的月末日期时,所有日期均为30日(例如10月实际月末为31日),仅当生成超过3个月时结果正确:

df = spark.createDataFrame([(1,)],['id'])

days = df.withColumn('last_dates', explode(expr('sequence(last_day(add_months(current_date(),-3)), last_day(add_months(current_date(), -1)), interval 1 month)')))

正确解决方案

方案1:Python环境(含Databricks)

使用dateutil.relativedelta处理月份偏移,准确计算每个月的月末:

from datetime import datetime
from dateutil.relativedelta import relativedelta

def get_last_n_month_ends(n_months):
    # 获取上月月末日期
    current_last_day = datetime.today().replace(day=1) - relativedelta(days=1)
    result = []
    for i in range(n_months):
        # 逐月往前偏移,取月末日期
        month_end = current_last_day - relativedelta(months=i)
        result.append(month_end.strftime('%Y-%m-%d'))
    # 反转列表让日期从旧到新排列(可根据需求调整顺序)
    return result[::-1]

# 示例:获取过去4个月的月末日期
print(get_last_n_month_ends(4))
# 输出(假设当前为2022年12月):['2022-08-31', '2022-09-30', '2022-10-31', '2022-11-30']

若Databricks中缺少dateutil,可通过%pip install python-dateutil命令安装。

方案2:PySpark环境

调整序列生成逻辑,先获取每月第一天再往前推1天得到月末,避免interval偏移导致的日期错误:

from pyspark.sql import functions as F

def get_spark_month_ends(n_months):
    # 生成从当前月往前n+1个月到上月的第一天序列
    start_date = F.add_months(F.trunc(F.current_date(), "month"), -(n_months))
    end_date = F.add_months(F.trunc(F.current_date(), "month"), -1)
    
    df = spark.createDataFrame([(1,)], ["id"])
    df = df.withColumn(
        "month_starts",
        F.explode(F.sequence(start_date, end_date, F.expr("interval 1 month")))
    ).withColumn(
        "month_ends",
        F.date_sub(F.col("month_starts"), 1)
    ).select("month_ends")
    
    # 转换为列表格式
    return [row[0] for row in df.collect()]

# 示例:获取过去4个月的月末日期
print(get_spark_month_ends(4))
# 输出(假设当前为2022年12月):['2022-08-31', '2022-09-30', '2022-10-31', '2022-11-30']

该方法通过每月第一天减1天的方式,确保得到准确的月末日期,不会出现固定30日的错误。


内容的提问来源于stack exchange,提问作者doubleD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 15:05:19