如何使用datetime Python模块计算当前日期六个月的日期?

How do I calculate the date six months from the current date using the datetime Python module?

我正在使用datetime python模块。我想从当前日期算起6个月的日期。有人能帮我一下吗?

我想从当前日期起6个月内生成日期的原因是要生成一个审核日期。如果用户将数据输入到系统中,则自输入数据之日起的审查日期为6个月。


我发现这个解决方案是好的。(这将使用python-dateutil扩展名)

1
2
3
4
from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

这种方法的优点是它可以处理28天、30天、31天等的问题。这在处理业务规则和方案(例如发票生成等)时非常有用。

1
2
3
4
5
$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)


好吧,这取决于你所说的从当前日期算起6个月是什么意思。

  • 使用自然月:

    1
    (day, month, year) = (day, (month+6)%12, year+(month+6)/12)
  • 使用银行定义,6*30:

    1
    date += datetime.timedelta(6*30)

  • 1
    2
    import datetime
    print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()


    对于月初计算:

    1
    2
    3
    4
    from datetime import timedelta
    from dateutil.relativedelta import relativedelta

    end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)


    "6个月"是什么意思?2009-02-13+6个月=2009-08-13还是2009-02-13+6*30天?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import mx.DateTime as dt

    #6 Months
    dt.now()+dt.RelativeDateTime(months=6)
    #result is '2009-08-13 16:28:00.84'

    #6*30 days
    dt.now()+dt.RelativeDateTime(days=30*6)
    #result is '2009-08-12 16:30:03.35'

    有关mx.datetime的详细信息


    此解决方案在12月份正常工作,而本页上的大多数答案都不正确。在使用模数(%)或整数除(//)之前,您需要首先将月份从基数1(ie jan=1)移到基数0(ie jan=0),否则11月(11)加1个月为12,当找到余数(12%12)时,余数为0。

    (不建议)(12月+1"或10月+1=12月!)

    1
    2
    3
    4
    def AddMonths(d,x):
        newmonth = ((( d.month - 1) + x ) % 12 ) + 1
        newyear  = d.year + ((( d.month - 1) + x ) / 12 )
        return datetime.date( newyear, newmonth, d.day)

    然而。。。这并不能解释1月31日+1个月这样的问题。所以我们回到操作-你说增加一个月是什么意思?一个解决办法是回溯到一个有效的日期,因为大多数人会假定1月的最后一天加上一个月等于2月的最后一天。这也适用于负月数。证明:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    >>> import datetime
    >>> AddMonths(datetime.datetime(2010,8,25),1)
    datetime.date(2010, 9, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),4)
    datetime.date(2010, 12, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),5)
    datetime.date(2011, 1, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),13)
    datetime.date(2011, 9, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),24)
    datetime.date(2012, 8, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),-1)
    datetime.date(2010, 7, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),0)
    datetime.date(2010, 8, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),-12)
    datetime.date(2009, 8, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),-8)
    datetime.date(2009, 12, 25)
    >>> AddMonths(datetime.datetime(2010,8,25),-7)
    datetime.date(2010, 1, 25)>>>


    对于Python的日期时间,没有直接的方法可以做到这一点。

    查看python-dateutil中的relativedelta类型。它允许您以月为单位指定时间增量。


    所以,这里有一个dateutil.relativedelta的例子,我发现它对于回顾过去的一年非常有用,到现在为止每次跳过一个月:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    >>> import datetime
    >>> from dateutil.relativedelta import relativedelta
    >>> today = datetime.datetime.today()
    >>> month_count = 0
    >>> while month_count < 12:
    ...  day = today - relativedelta(months=month_count)
    ...  print day
    ...  month_count += 1
    ...
    2010-07-07 10:51:45.187968
    2010-06-07 10:51:45.187968
    2010-05-07 10:51:45.187968
    2010-04-07 10:51:45.187968
    2010-03-07 10:51:45.187968
    2010-02-07 10:51:45.187968
    2010-01-07 10:51:45.187968
    2009-12-07 10:51:45.187968
    2009-11-07 10:51:45.187968
    2009-10-07 10:51:45.187968
    2009-09-07 10:51:45.187968
    2009-08-07 10:51:45.187968

    与其他答案一样,您必须弄清楚"6个月后"的实际含义。如果您的意思是"未来6年内的某个月的今天",那么应该这样做:

    1
    datetime.datetime.now() + relativedelta(months=6)

    我知道这是6个月的时间,但是如果你增加一个月,谷歌会给出"在python中增加几个月"的答案:

    1
    2
    3
    4
    5
    import calendar

    date = datetime.date.today()    //Or your date

    datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

    这将计算当前月份中的天数并将其添加到当前日期,使用365/12,如果您重复日期,一年中的1/12可能会导致短/长月份的问题。


    使用python 3.x,您可以这样做:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from datetime import datetime, timedelta
    from dateutil.relativedelta import *

    date = datetime.now()
    print(date)
    # 2018-09-24 13:24:04.007620

    date = date + relativedelta(months=+6)
    print(date)
    # 2019-03-24 13:24:04.007620

    但您需要安装python dateutil模块:

    1
    pip install python-dateutil

    只需使用TimeTuple方法提取月份,添加月份并构建一个新的DateObject。如果已经有了这种方法,我就不知道了。

    1
    2
    3
    4
    5
    6
    import datetime

    def in_the_future(months=1):
        year, month, day = datetime.date.today().timetuple()[:3]
        new_month = month + months
        return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

    API有点笨拙,但可以作为一个例子。显然也不适用于2008-01-31+1个月等角落案件。:)


    dateutil包实现了这类功能。但要知道,这将是幼稚的,正如其他人已经指出的。


    使用python标准库,即不使用dateutil或其他库,并解决"2月31日"问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import datetime
    import calendar

    def add_months(date, months):
        months_count = date.month + months

        # Calculate the year
        year = date.year + int(months_count / 12)

        # Calculate the month
        month = (months_count % 12)
        if month == 0:
            month = 12

        # Calculate the day
        day = date.day
        last_day_of_month = calendar.monthrange(year, month)[1]
        if day > last_day_of_month:
            day = last_day_of_month

        new_date = datetime.date(year, month, day)
        return new_date

    测试:

    1
    2
    3
    4
    5
    6
    7
    >>>date = datetime.date(2018, 11, 30)

    >>>print(date, add_months(date, 3))
    (datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

    >>>print(date, add_months(date, 14))
    (datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

    我有更好的方法来解决"2月31日"的问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def add_months(start_date, months):
        import calendar

        year = start_date.year + (months / 12)
        month = start_date.month + (months % 12)
        day = start_date.day

        if month > 12:
            month = month % 12
            year = year + 1

        days_next = calendar.monthrange(year, month)[1]
        if day > days_next:
            day = days_next

        return start_date.replace(year, month, day)

    我认为它也适用于负数(减去月份),但我没有做过很多测试。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import time

    def add_month(start_time, months):  

            ret = time.strptime(start_time, '%Y-%m-%d')
            t = list(ret)

            t[1] += months

            if t[1] > 12:
                t[0] += 1 + int(months / 12)

                t[1] %= 12

            return int(time.mktime(tuple(t)))

    pyqt4的qdate类具有addmonths函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>>from PyQt4.QtCore import QDate  
    >>>dt = QDate(2009,12,31)  
    >>>required = dt.addMonths(6)

    >>>required
    PyQt4.QtCore.QDate(2010, 6, 30)

    >>>required.toPyDate()
    datetime.date(2010, 6, 30)

    这个怎么样?不使用其他库(dateutiltimedelta吗?基于瓦特克的回答,我做到了这一点,我相信这是可行的:

    1
    2
    3
    4
    import datetime

    today = datetime.date.today()
    six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

    我试过使用timedelta,但因为它计算天数,365/26*356/12并不总是翻译为6个月,而是182天。例如

    1
    2
    3
    4
    5
    6
    day = datetime.date(2015, 3, 10)
    print day
    >>> 2015-03-10

    print (day + datetime.timedelta(6*365/12))
    >>> 2015-09-08

    我认为,我们通常假定从某一天起的6个月将在该月的同一天着陆,但6个月后着陆(即2015-03-10->2015-09-10,而不是2015-09-08)

    我希望你觉得这有帮助。


    已修改addMonths(),以便在Zope中使用并处理无效的日期:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def AddMonths(d,x):
        days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
        newyear  = d.year() + ((( d.month() - 1) + x ) // 12 )
        if d.day() > days_of_month[newmonth-1]:
          newday = days_of_month[newmonth-1]
        else:
          newday = d.day()
        return DateTime( newyear, newmonth, newday)


    获取x个月之后/之前的下一个日期的常规函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    from datetime import date

    def after_month(given_date, month):
        yyyy = int(((given_date.year * 12 + given_date.month) + month)/12)
        mm = int(((given_date.year * 12 + given_date.month) + month)%12)

        if mm == 0:
            yyyy -= 1
            mm = 12
        return given_date.replace(year=yyyy, month=mm)


    if __name__ =="__main__":
        today = date.today()
        print(today)

        for mm in [-12, -1, 0, 1, 2, 12, 20 ]:
            next_date = after_month(today, mm)
            print(next_date)


    假设您的日期时间变量称为日期:

    1
    2
    3
    date=datetime.datetime(year=date.year+int((date.month+6)/12),
                           month=(date.month+6)%13 + (1 if (date.month +
                           months>12) else 0), day=date.day)

    下面是一个示例,它允许用户决定如何返回一个日期,其中日期大于月份中的天数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    def add_months(date, months, endOfMonthBehaviour='RoundUp'):
        assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
            'Unknown end of month behaviour'
        year = date.year + (date.month + months - 1) / 12
        month = (date.month + months - 1) % 12 + 1
        day = date.day
        last = monthrange(year, month)[1]
        if day > last:
            if endOfMonthBehaviour == 'RoundDown' or \
                endOfMonthBehaviour == 'RoundOut' and months < 0 or \
                endOfMonthBehaviour == 'RoundIn' and months > 0:
                day = last
            elif endOfMonthBehaviour == 'RoundUp' or \
                endOfMonthBehaviour == 'RoundOut' and months > 0 or \
                endOfMonthBehaviour == 'RoundIn' and months < 0:
                # we don't need to worry about incrementing the year
                # because there will never be a day in December > 31
                month += 1
                day = 1
        return datetime.date(year, month, day)


    >>> from calendar import monthrange
    >>> import datetime
    >>> add_months(datetime.datetime(2016, 1, 31), 1)
    datetime.date(2016, 3, 1)
    >>> add_months(datetime.datetime(2016, 1, 31), -2)
    datetime.date(2015, 12, 1)
    >>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
    datetime.date(2015, 11, 30)

    修改了Johannes Wei在案例1"新月份=121"中的回答。这对我很有效。月份可以是正的也可以是负的。

    1
    2
    3
    4
    def addMonth(d,months=1):
        year, month, day = d.timetuple()[:3]
        new_month = month + months
        return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)


    从这个答案中,请参见ParseDateTime。下面是代码示例。更多细节:单元测试中有许多自然语言->YYYY-MM-DD转换示例,以及明显的ParseDateTime转换挑战/错误。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import time, calendar
    from datetime import date

    # from https://github.com/bear/parsedatetime
    import parsedatetime as pdt

    def print_todays_date():
        todays_day_of_week = calendar.day_name[date.today().weekday()]
        print"today's date =" + todays_day_of_week + ', ' + \
                                  time.strftime('%Y-%m-%d')

    def convert_date(natural_language_date):
        cal = pdt.Calendar()
        (struct_time_date, success) = cal.parse(natural_language_date)
        if success:
            formal_date = time.strftime('%Y-%m-%d', struct_time_date)
        else:
            formal_date = '(conversion failed)'
        print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

    print_todays_date()
    convert_date('6 months')

    上述代码从MacOSX机器生成以下内容:

    1
    2
    3
    4
    $ ./parsedatetime_simple.py
    today's date = Wednesday, 2015-05-13
    6 months     -> 2015-11-13
    $

    我这样解决了这个问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import calendar
    from datetime import datetime
    moths2add = 6
    now = datetime.now()
    current_year = now.year
    current_month = now.month
    #count days in months you want to add using calendar module
    days = sum(
      [calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)]
        )
    print now + days


    还有另一个解决方案-希望有人会喜欢它:

    1
    2
    def add_months(d, months):
        return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

    对于所有情况,此解决方案在第29、30、31天内都不起作用,因此需要更强大的解决方案(不再那么好了:):

    1
    2
    3
    4
    5
    6
    7
    8
    def add_months(d, months):
        for i in range(4):
            day = d.day - i
            try:
                return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
            except:
                pass
        raise Exception("should not happen")

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    import datetime


    '''
    Created on 2011-03-09

    @author: tonydiep
    '''


    def add_business_months(start_date, months_to_add):
       """
        Add months in the way business people think of months.
        Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
        Method: Add the number of months, roll back the date until it becomes a valid date
       """

        # determine year
        years_change = months_to_add / 12

        # determine if there is carryover from adding months
        if (start_date.month + (months_to_add % 12) > 12 ):
            years_change = years_change + 1

        new_year = start_date.year + years_change

        # determine month
        work = months_to_add % 12
        if 0 == work:
            new_month = start_date.month
        else:
            new_month = (start_date.month + (work % 12)) % 12

        if 0 == new_month:
            new_month = 12

        # determine day of the month
        new_day = start_date.day
        if(new_day in [31, 30, 29, 28]):
            #user means end of the month
            new_day = 31


        new_date = None
        while (None == new_date and 27 < new_day):
            try:
                new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
            except:
                new_day = new_day - 1   #wind down until we get to a valid date

        return new_date


    if __name__ == '__main__':
        #tests
        dates = [datetime.date(2011, 1, 31),
                 datetime.date(2011, 2, 28),
                 datetime.date(2011, 3, 28),
                 datetime.date(2011, 4, 28),
                 datetime.date(2011, 5, 28),
                 datetime.date(2011, 6, 28),
                 datetime.date(2011, 7, 28),
                 datetime.date(2011, 8, 28),
                 datetime.date(2011, 9, 28),
                 datetime.date(2011, 10, 28),
                 datetime.date(2011, 11, 28),
                 datetime.date(2011, 12, 28),
                 ]
        months = range(1, 24)
        for start_date in dates:
            for m in months:
                end_date = add_business_months(start_date, m)
                print("%s\t%s\t%s" %(start_date, end_date, m))

    这就是我想到的。它移动了正确的月份和年份,但忽略了天数(这是我在这种情况下需要的)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import datetime

    month_dt = 4
    today = datetime.date.today()
    y,m = today.year, today.month
    m += month_dt-1
    year_dt = m//12
    new_month = m%12
    new_date = datetime.date(y+year_dt, new_month+1, 1)

    我使用replace()方法编写了这个递归函数。dtdatetime.datetime对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def month_timedelta(dt, m):
        y = m // 12
        dm = m % 12
        if y == 0:
            if dt.month + m <= 12:
                return dt.replace(month = dt.month + m)
            else:
                dy = (dt.month + m) // 12
                ndt = dt.replace(year=dt.year + dy)
                return ndt.replace(month=(ndt.month + m) % 12)
        else:
            return month_timedelta(dt.replace(year=dt.year + y),dm)

    用户417751修改了先前的答案。也许不是用Python的方式,但它需要处理不同的月份长度和闰年。在这种情况下,2012年1月31日+1个月=2012年2月29日。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import datetime
    import calendar

    def add_mths(d, x):
        newday = d.day
        newmonth = (((d.month - 1) + x) % 12) + 1
        newyear  = d.year + (((d.month - 1) + x) // 12)
        if newday > calendar.mdays[newmonth]:
            newday = calendar.mdays[newmonth]
            if newyear % 4 == 0 and newmonth == 2:
                newday += 1
        return datetime.date(newyear, newmonth, newday)

    另一种解决方案是:计算下一个n个月的月份天数总和,并将结果添加到当前日期。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import calendar
    import datetime

    def date_from_now(months):
        today = datetime.datetime.today()

        month = today.month
        year = today.year
        sum_days = 0

        for i in range(int(months)):
            month += 1

            if month == 13:
                month = 1
                year += 1

            sum_days += calendar.monthrange(year, month)[1]

        return datetime.date.today() + datetime.timedelta(sum_days)

    print(date_from_now(12)) # if to day is 2017-01-01, output: 2019-01-01

    我迟到了,但是

    查看ken reitz maya模块,

    https://github.com/kennethreitz/maya

    这样可以帮助您,只需将hours=1改为days=1或years=1

    1
    2
    3
    4
    5
    6
    7
    >>> from maya import MayaInterval

    # Create an event that is one hour long, starting now.
    >>> event_start = maya.now()
    >>> event_end = event_start.add(hours=1)

    >>> event = MayaInterval(start=event_start, end=event_end)


    我使用此功能更改年和月,但保留日:

    1
    2
    3
    4
    5
    6
    def replace_month_year(date1, year2, month2):
        try:
            date2 = date1.replace(month = month2, year = year2)
        except:
            date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
        return date2

    你应该写:

    1
    2
    3
    new_year = my_date.year + (my_date.month + 6) / 12
    new_month = (my_date.month + 6) % 12
    new_date = replace_month_year(my_date, new_year, new_month)

    使用python datetime模块向datetime.today()添加6个月的时间增量。

    http://docs.python.org/library/datetime.html网站

    你当然要解决魏先生提出的问题吗?--你说6个月是什么意思?


    我认为这样做会更安全,而不是手动增加天数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import datetime
    today = datetime.date.today()

    def addMonths(dt, months = 0):
        new_month = months + dt.month
        year_inc = 0
        if new_month>12:
            year_inc +=1
            new_month -=12
        return dt.replace(month = new_month, year = dt.year+year_inc)

    newdate = addMonths(today, 6)


    当我需要添加月或年并且不想导入更多的库时,这就是我要做的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    import datetime
    __author__ = 'Daniel Margarido'


    # Check if the int given year is a leap year
    # return true if leap year or false otherwise
    def is_leap_year(year):
        if (year % 4) == 0:
            if (year % 100) == 0:
                if (year % 400) == 0:
                    return True
                else:
                    return False
            else:
                return True
        else:
            return False


    THIRTY_DAYS_MONTHS = [4, 6, 9, 11]
    THIRTYONE_DAYS_MONTHS = [1, 3, 5, 7, 8, 10, 12]

    # Inputs -> month, year Booth integers
    # Return the number of days of the given month
    def get_month_days(month, year):
        if month in THIRTY_DAYS_MONTHS:   # April, June, September, November
            return 30
        elif month in THIRTYONE_DAYS_MONTHS:   # January, March, May, July, August, October, December
            return 31
        else:   # February
            if is_leap_year(year):
                return 29
            else:
                return 28

    # Checks the month of the given date
    # Selects the number of days it needs to add one month
    # return the date with one month added
    def add_month(date):
        current_month_days = get_month_days(date.month, date.year)
        next_month_days = get_month_days(date.month + 1, date.year)

        delta = datetime.timedelta(days=current_month_days)
        if date.day > next_month_days:
            delta = delta - datetime.timedelta(days=(date.day - next_month_days) - 1)

        return date + delta


    def add_year(date):
        if is_leap_year(date.year):
            delta = datetime.timedelta(days=366)
        else:
            delta = datetime.timedelta(days=365)

        return date + delta


    # Validates if the expected_value is equal to the given value
    def test_equal(expected_value, value):
        if expected_value == value:
            print"Test Passed"
            return True

        print"Test Failed :" + str(expected_value) +" is not equal to" str(value)
        return False

    # Test leap year
    print"---------- Test leap year ----------"
    test_equal(True, is_leap_year(2012))
    test_equal(True, is_leap_year(2000))
    test_equal(False, is_leap_year(1900))
    test_equal(False, is_leap_year(2002))
    test_equal(False, is_leap_year(2100))
    test_equal(True, is_leap_year(2400))
    test_equal(True, is_leap_year(2016))

    # Test add month
    print"---------- Test add month ----------"
    test_equal(datetime.date(2016, 2, 1), add_month(datetime.date(2016, 1, 1)))
    test_equal(datetime.date(2016, 6, 16), add_month(datetime.date(2016, 5, 16)))
    test_equal(datetime.date(2016, 3, 15), add_month(datetime.date(2016, 2, 15)))
    test_equal(datetime.date(2017, 1, 12), add_month(datetime.date(2016, 12, 12)))
    test_equal(datetime.date(2016, 3, 1), add_month(datetime.date(2016, 1, 31)))
    test_equal(datetime.date(2015, 3, 1), add_month(datetime.date(2015, 1, 31)))
    test_equal(datetime.date(2016, 3, 1), add_month(datetime.date(2016, 1, 30)))
    test_equal(datetime.date(2016, 4, 30), add_month(datetime.date(2016, 3, 30)))
    test_equal(datetime.date(2016, 5, 1), add_month(datetime.date(2016, 3, 31)))

    # Test add year
    print"---------- Test add year ----------"
    test_equal(datetime.date(2016, 2, 2), add_year(datetime.date(2015, 2, 2)))
    test_equal(datetime.date(2001, 2, 2), add_year(datetime.date(2000, 2, 2)))
    test_equal(datetime.date(2100, 2, 2), add_year(datetime.date(2099, 2, 2)))
    test_equal(datetime.date(2101, 2, 2), add_year(datetime.date(2100, 2, 2)))
    test_equal(datetime.date(2401, 2, 2), add_year(datetime.date(2400, 2, 2)))

    只需创建一个datetime.date()对象,调用add_month(date)添加一个月,调用add_year(date)添加一年。


    我修改了Tony Diep的答案,可能稍微优雅一些(当然是python 2,匹配问题的日期和原始答案,对于python 3,根据需要进行修改,至少包括///):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def add_months(date, months):
        month = date.month + months - 1
        year = date.year + (month / 12)
        month = (month % 12) + 1
        day = date.day
        while (day > 0):
            try:
                new_date = date.replace(year=year, month=month, day=day)
                break
            except:
                day = day - 1    
        return new_date

    根据"业务需求"的解释添加月份,日期映射超过月底后,应映射到月底,而不是下个月。


    我们可能应该使用dateutil.relativedelta

    不过,为了学术上的兴趣,我会补充一点,在我发现它之前,我打算使用这个:

    尝试:&vexpdt=k.today.replace(k.today.year+(k.today.month+6)//12(k.today.month+5)%12+1,k.today.day)除:&vexpdt=k.today.replace(k.today.year+(k.today.month+6)//12,(k.today.month+6)%12+1,1)-时间差(days=1)

    这看起来很简单,但仍然抓住了所有问题,如29、30、31

    它还可以通过做-时间增量工作-6个月

    注意-不要被k混淆。今天它只是我程序中的一个变量。


    在这个函数中,n可以是正的,也可以是负的。

    1
    2
    3
    4
    def addmonth(d, n):
        n += 1
        dd = datetime.date(d.year + n/12, d.month + n%12, 1)-datetime.timedelta(1)
        return datetime.date(dd.year, dd.month, min(d.day, dd.day))

    使用下面给出的函数,您可以获得x个月之后/之前的日期。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    from datetime import date

    def next_month(given_date, month):
        yyyy = int(((given_date.year * 12 + given_date.month) + month)/12)
        mm = int(((given_date.year * 12 + given_date.month) + month)%12)

        if mm == 0:
            yyyy -= 1
            mm = 12
        return given_date.replace(year=yyyy, month=mm)


    if __name__ =="__main__":
        today = date.today()
        print(today)

        for mm in [-12, -1, 0, 1, 2, 12, 20 ]:
            next_date = next_month(today, mm)
            print(next_date)


    我找不到这个问题的确切解决方案,所以我将发布我的解决方案,以防使用stantard日历和datetime libs有任何帮助。这适用于加和减月份,并说明月末滚动和最后一个月的天数少于最初一个月的情况。我还有一个更通用的解决方案,如果你想寻找更复杂的操作,它会增加规则的间隔(天、月、年、季度、字长等),比如:"1米"、"-9米"、"-1.5年"、"-3q"、"1秒"等等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    from datetime import datetime
    from calendar import monthrange
    def date_bump_months(start_date, months):
       """
        bumps months back and forth.
        --> if initial date is end-of-month, i will move to corresponding month-end
        --> ir inital date.day is greater than end of month of final date, it casts it to momth-end
       """

        signbit = -1 if months < 0 else 1
        d_year, d_month = divmod(abs(months),12)    
        end_year = start_date.year + d_year*signbit
        end_month = 0
        if signbit ==-1:            
            if d_month < start_date.month:
                end_month = start_date.month - d_month
            else:
                end_year -=1
                end_month = 12 - (d_month - start_date.month)
        else:
            end_month +=start_date.month
            if end_month  > 12:
                end_year +=1
                end_month -=12
        # check if we are running end-of-month dates
        eom_run = monthrange(start_date.year, start_date.month)[1]==start_date.day
        eom_month = monthrange((end_year), (end_month))[1]
        if eom_run:
            end_day = eom_month
        else:
            end_day = min(start_date.day, eom_month )    
        return date(end_year, end_month, end_day)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        def addDay(date, number):
            for i in range(number)
                #try to add a day
                try:
                    date = date.replace(day = date.day + 1)
                #in case it's impossible ex:january 32nd add a month and restart at day 1
                except:
                    #add month part
                    try:
                        date = date.replace(month = date.month +1, day = 1)
                    except:
                        date = date.replace(year = date.year +1, month = 1, day = 1)

    对于每个仍在阅读这篇文章的人。我认为这段代码要清楚得多,特别是与使用modulo%的代码相比。

    对不起,任何语法错误,英语不是我的主要语言