我需要增加一个datetime值的月份

next_month = datetime.datetime(mydate.year, mydate.month+1, 1)

当月份为12时,它变成13,并引发错误“month必须在1..12”。(我预计时间会增加)

我想使用timedelta,但它不带month参数。 有一个relativedelta python包,但我不想只为此安装它。 还有一个使用strtotime的解决方案。

time = strtotime(str(mydate));
next_month = date("Y-m-d", strtotime("+1 month", time));

我不想从datetime转换为str再转换为time,再转换为datetime;因此,它仍然是一个图书馆

有人有像使用timedelta一样好的简单的解决方案吗?


当前回答

这是我想到的

from calendar  import monthrange

def same_day_months_after(start_date, months=1):
    target_year = start_date.year + ((start_date.month + months) / 12)
    target_month = (start_date.month + months) % 12
    num_days_target_month = monthrange(target_year, target_month)[1]
    return start_date.replace(year=target_year, month=target_month, 
        day=min(start_date.day, num_days_target_month))

其他回答

这是我的盐:

current = datetime.datetime(mydate.year, mydate.month, 1)
next_month = datetime.datetime(mydate.year + int(mydate.month / 12), ((mydate.month % 12) + 1), 1)

简单快捷:)

from datetime import timedelta
try:
    next = (x.replace(day=1) + timedelta(days=31)).replace(day=x.day)
except ValueError:  # January 31 will return last day of February.
    next = (x + timedelta(days=31)).replace(day=1) - timedelta(days=1)

如果你只想要下个月的第一天:

next = (x.replace(day=1) + timedelta(days=31)).replace(day=1)

这个实现可能对处理账单的人有一定的价值。

如果您正在处理账单,您可能希望得到“下个月相同的日期(如果可能的话)”,而不是“增加一年的1/12”。

让人困惑的是如果你连续做这个,你实际上需要考虑两个值。否则,对于任何超过27日的日期,你将继续失去几天,直到闰年后的27日。

你需要考虑的价值:

您想要添加一个月的值 你开始的那一天

这样当你加一个月的时候,如果你从31号降到了30号,那么下个月有这一天的时候,你就会回到31号。

我是这样做的:

def closest_date_next_month(year, month, day):
    month = month + 1
    if month == 13:
        month = 1
        year  = year + 1


    condition = True
    while condition:
        try:
            return datetime.datetime(year, month, day)
        except ValueError:
            day = day-1
        condition = day > 26

    raise Exception('Problem getting date next month')

paid_until = closest_date_next_month(
                 last_paid_until.year, 
                 last_paid_until.month, 
                 original_purchase_date.day)  # The trick is here, I'm using the original date, that I started adding from, not the last one

使用monthdelta包,它就像timedelta一样工作,但适用于日历月,而不是天/小时/等等。

这里有一个例子:

from monthdelta import MonthDelta

def prev_month(date):
    """Back one month and preserve day if possible"""
    return date + MonthDelta(-1)

将其与DIY方法进行比较:

def prev_month(date):
    """Back one month and preserve day if possible"""
   day_of_month = date.day
   if day_of_month != 1:
           date = date.replace(day=1)
   date -= datetime.timedelta(days=1)
   while True:
           try:
                   date = date.replace(day=day_of_month)
                   return date
           except ValueError:
                   day_of_month -= 1               

使用time对象的示例:

start_time = time.gmtime(time.time())    # start now

#increment one month
start_time = time.gmtime(time.mktime([start_time.tm_year, start_time.tm_mon+1, start_time.tm_mday, start_time.tm_hour, start_time.tm_min, start_time.tm_sec, 0, 0, 0]))