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

Python中add_months函数aux_date无法递增问题及修正咨询

日期增加月份函数的问题解析

问题背景

编写了用于给日期增加指定月份的Python函数add_months,但原函数运行时发现aux_date变量未在循环中逐步累加月份天数,反而每次基于原始日期计算,导致日期无法递增。

原函数代码

import re, datetime


def add_months(datestr, months):
    ref_year, ref_month = "", ""
    ref_year_is_leap_year = False

    aux_date = str(datetime.datetime.strptime(datestr, "%Y-%m-%d"))
    print(repr(aux_date))

    for i_month in range(int(months)):
        # I add a unit since the months are "numerical quantities",
        # that is, they are expressed in natural numbers, so I need it
        # to start from 1 and not from 0 like the iter variable in python

        i_month = i_month + 1

        m1 = re.search(
            r"(?P<year>\d*)-(?P<month>\d{2})-(?P<startDay>\d{2})",
            aux_date,
            re.IGNORECASE,
        )
        if m1:
            ref_year, ref_month = (
                str(m1.groups()[0]).strip(),
                str(m1.groups()[1]).strip(),
            )

        number_of_days_in_each_month = {
            "01": "31",
            "02": "28",
            "03": "31",
            "04": "30",
            "05": "31",
            "06": "30",
            "07": "31",
            "08": "31",
            "09": "30",
            "10": "31",
            "11": "30",
            "12": "31",
        }

        n_days_in_this_i_month = number_of_days_in_each_month[ref_month]
        print(n_days_in_this_i_month)  # nro days to increment in each i month iteration

        if (
            int(ref_year) % 4 == 0
            and int(ref_year) % 100 == 0
            and int(ref_year) % 400 != 0
        ):
            ref_year_is_leap_year = True  # divisible entre 4 y 10 y no entre 400, para determinar que sea un año bisciesto

        if ref_year_is_leap_year == True and ref_month == "02":
            n_days_in_this_i_month = str(int(n_days_in_this_i_month) + 1)  # 28 --> 29

        aux_date = (
            datetime.datetime.strptime(datestr, "%Y-%m-%d")
            + datetime.timedelta(days=int(n_days_in_this_i_month))
        ).strftime("%Y-%m-%d")

        print(repr(aux_date))

    return aux_date


print(repr(add_months("2022-12-30", "3")))

优化后的函数代码

def add_months(datestr, months):
    ref_year, ref_month = "", ""
    ref_year_is_leap_year = False #condicional booleano, cuya logica binaria intenta establecer si es o no bisiesto el año tomado como referencia

    aux_date = datetime.datetime.strptime(datestr, "%Y-%m-%d")

    for i_month in range(int(months)):

        i_month = i_month + 1 # I add a unit since the months are "numerical quantities", that is, they are expressed in natural numbers, so I need it to start from 1 and not from 0 like the iter variable in python

        m1 = re.search( r"(?P<year>\d*)-(?P<month>\d{2})-(?P<startDay>\d{2})", str(aux_date), re.IGNORECASE, )
        if m1:
            ref_year, ref_month = ( str(m1.groups()[0]).strip(), str( int(m1.groups()[1]) + 1).strip(), )
        
        if( len(ref_month) == 1 ): ref_month = "0" + ref_month
        if( int(ref_month) > 12 ): ref_month = "01"
        print(ref_month)

        number_of_days_in_each_month = {
            "01": "31",
            "02": "28",
            "03": "31",
            "04": "30",
            "05": "31",
            "06": "30",
            "07": "31",
            "08": "31",
            "09": "30",
            "10": "31",
            "11": "30",
            "12": "31",
        }


        n_days_in_this_i_month = number_of_days_in_each_month[ref_month]

        if ( int(ref_year) % 4 == 0 and int(ref_year) % 100 != 0 ) or ( int(ref_year) % 400 == 0 ): ref_year_is_leap_year = True ref_year_is_leap_year = True  # divisible entre 4 y 10 y no entre 400, para determinar que sea un año bisciesto
        if ref_year_is_leap_year == True and ref_month == "02": n_days_in_this_i_month = str(int(n_days_in_this_i_month) + 1)  # 28 --> 29

        print(n_days_in_this_i_month)  # nro days to increment in each i month iteration

        aux_date = aux_date + datetime.timedelta(days=int(n_days_in_this_i_month))

    return datetime.datetime.strftime(aux_date, "%Y-%m-%d")

问题解答

1. 原函数中aux_date无法递增的根本原因

核心问题出在循环内更新aux_date的代码:

aux_date = (
    datetime.datetime.strptime(datestr, "%Y-%m-%d")
    + datetime.timedelta(days=int(n_days_in_this_i_month))
).strftime("%Y-%m-%d")

每次循环都基于原始输入的datestr解析出初始日期,再加上当月天数,而不是用上一次循环已经更新后的aux_date进行累加。这就导致每次循环得到的都是“原始日期+1个月”的结果,完全没有增量迭代的效果,自然会出现日期停滞的问题。

此外原函数还有两处次要错误:

  • 闰年判断逻辑写反:当前条件判断的是平年的情况,却错误设置了ref_year_is_leap_year = True。
  • 把aux_date转成字符串后用正则解析,既冗余又容易出错,datetime对象本身可直接获取年、月、日属性。

2. 更新后的函数是否正确实现了日期增量累加?

更新后的函数修复了核心的累加问题,但仍存在多处bug和逻辑缺陷,没有完全正确实现需求:

已修复的部分

  • aux_date改为存储datetime对象,循环中用aux_date = aux_date + datetime.timedelta(days=int(n_days_in_this_i_month))实现了基于当前日期的累加,解决了停滞问题。
  • 修正了闰年判断的逻辑条件,现在能正确识别闰年。

仍存在的问题

  1. 语法错误:闰年判断行重复写了ref_year_is_leap_year = True,会直接抛出语法错误,无法运行。
  2. 月份处理逻辑错误:
    • 解析aux_date时把当前月份加1作为ref_month,但当月份是12时,加1变成13,后续虽设为01,但未同步更新年份,导致闰年判断仍使用旧年份,会出现错误(比如2022-12累加后进入2023年,但ref_year还是2022)。
    • 完全没必要用正则解析datetime字符串,直接用aux_date.year、aux_date.month就能获取准确的年、月信息,正则解析既冗余又容易引入格式错误。
  3. 冗余代码:i_month = i_month + 1完全没用,循环次数由range(int(months))控制,该变量未参与任何逻辑计算。
  4. 语义偏差:通过累加每个月的天数来实现“加N个月”,和实际业务中“加N个月”的语义不符。比如原始日期是2023-01-31,加1个月按函数逻辑会加31天得到2023-03-03,但实际期望通常是2023-02-28(非闰年),这种月底场景会出现不符合预期的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:45:34