关于日期:Python:如何将月份添加到2012年12月并获得2013年1月?

Python : How to add month to December 2012 and get January 2013?

1
2
3
>>> start_date = date(1983, 11, 23)
>>> start_date.replace(month=start_date.month+1)
datetime.date(1983, 12, 23)

我一到这个月就开始工作了。

1
2
3
4
5
>>> start_date = date(1983, 12, 23)
>>> start_date.replace(month=start_date.month+1)
Traceback (most recent call last):
  File"<stdin>", line 1, in <module>
ValueError: month must be in 1..12

我怎样才能不断地增加月份?当新月份增加到12月时,月份会增加?


dateutil库对于这样的计算很有用:

1
2
>>> start_date + relativedelta(months=2)
datetime.date(1984, 1, 23)


使用datetime.timedeltacalendar.monthrange时:

1
2
3
4
5
6
>>> from datetime import date, timedelta
>>> import calendar
>>> start_date = date(1983, 12, 23)
>>> days_in_month = calendar.monthrange(start_date.year, start_date.month)[1]
>>> start_date + timedelta(days=days_in_month)
datetime.date(1984, 1, 23)


1
2
3
4
5
6
7
8
try:
    start_date.replace(month=start_date.month+1)
except ValueError:
    if start_date.month == 12:
         start_date.replace(month=1)
         start_date.replace(year=start_date.year+1)
    else:
         raise

你必须决定如何处理像1月31日+1个月=2月31日这样的奇怪案件(这是不存在的)。但我倾向于使用TimeDelta添加到您的日期中,如:

1
2
import datetime as dt
dt.datetime.now() + dt.timedelta(days=30)

在这里,您可以根据当前或下个月的大小选择天数,或者其他一些这样的值,这样就不会溢出下个月。


如果您希望对此问题有一个更通用的解决方案,例如将天、月和年混合到一个日期中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time, datetime, calendar
def upcount(dt, years=0, months=0, **kwargs):
    if months:
        total_months = dt.month + months
        month_years, months = divmod(total_months, 12)
        if months == 0:
            month_years -= 1
            months = 12
        years += month_years
    else:
        months = dt.month

    years = dt.year + years
    try:
        dt = dt.replace(year=years, month=months)
    except ValueError:
        # 31st march -> 31st april gives this error
        max_day = calendar.monthrange(years, months)[1]
        dt = dt.replace(year=years, month=months, day=max_day)

    if kwargs:
        dt += datetime.timedelta(**kwargs)
    return dt