首页 文章

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

提问于
浏览
261

我正在使用datetime Python模块 . 我想计算从当前日期起6个月的日期 . 有人可以给我一点帮助吗?

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

30 回答

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

    我发现这个解决方案很好 . (这使用python-dateutil extension

    from datetime import date
    from dateutil.relativedelta import relativedelta
    
    six_months = date.today() + relativedelta(months=+6)
    

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

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

    那么,这取决于您从当前日期起6个月的含义 .

    • 使用自然月份:
    (day, month, year) = (day, (month+6)%12, year+(month+6)/12)
    
    • 使用银行家的定义,6 * 30:
    date += datetime.timedelta(6*30)
    
  • 1

    对于月初计算的开始:

    from datetime import timedelta
    from dateutil.relativedelta import relativedelta
    
    end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
    
  • 0

    你是什么意思'6个月' . 是2009-02-13 6个月== 2009-08-13还是2009-02-13 6 * 30天?

    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

  • 8

    此解决方案适用于12月,此页面上的大多数答案都没有 . 在使用模数(%)或整数除法(//)之前,您需要首先将月份从基数1(即Jan = 1)转移到基数0(即Jan = 0),否则11月(11)加1个月给出12 ,当找到余数(12%12)给出0 .

    (并且不建议“(月%12)1”或10月1日= 12月!)

    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日那样解决问题 . 所以我们回到OP - 添加一个月是什么意思?一个解决方案是回溯直到你到达有效的一天,因为大多数人会认为jan的最后一天,加上一个月,等于2月的最后一天 . 这也将在负数月份工作 . 证明:

    >>> 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)>>>
    
  • 2

    我知道这已经有6个月了,但是如果你要添加一个月,谷歌的答案显示“在python中增加几个月”:

    import calendar
    
    date = datetime.date.today()    //Or your date
    
    datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])
    

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

  • 6

    使用Python的日期时间没有直接的方法 .

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

  • 44

    所以,这里有一个 dateutil.relativedelta 的例子,我发现它可以用于迭代过去的一年,每次跳过一个月到现在的日期:

    >>> 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个月后”找出你的真正含义 . 如果你的意思是“未来六个月的今天这个月”,那么这样做:

    datetime.datetime.now() + relativedelta(months=6)
    
  • 0

    Dateutil package已实现此类功能 . 但请注意,这将是天真的,正如其他人已经指出的那样 .

  • 0

    只需使用timetuple方法提取月份,添加月份并构建新的日期对象 . 如果有一个已经存在的方法,我不知道 .

    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, day)
    

    API有点笨拙,但作为一个例子 . 显然也不会像2008-01-31 1月那样在角落案件上工作 . :)

  • 0

    使用Python标准库,即没有 dateutil 或其他,并解决'February 31st'问题:

    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
    

    测试:

    >>>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))
    
  • 4

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

    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 模块:

    pip install python-dateutil
    
  • 2

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

    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

    PyQt4的QDate类具有addmonths函数 .

    >>>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)
    
  • 17

    修改AddMonths()以在Zope中使用并处理无效的日期数:

    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)
    
  • 10
    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)))
    
  • 1

    这个怎么样?不使用其他库( dateutil )或 timedelta ? Build 在vartec的答案上,我这样做了,我相信它有效:

    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天 . 例如

    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

    我希望你觉得这有帮助 .

  • 765

    我这样解决了这个问题:

    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
    
  • 6

    在1new_month = 121的案例中修改了Johannes Wei的答案 . 这对我来说非常有效 . 这几个月可能是积极的或消极的 .

    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)
    
  • 23

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

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

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

    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")
    
  • 11

    this answer,请参阅parsedatetime . 代码示例如下 . 更多细节:unit test with many natural-language -> YYYY-MM-DD conversion examples,明显parsedatetime conversion challenges/bugs .

    #!/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机器生成以下内容:

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

    这是一个示例,允许用户决定如何返回日期大于该月份天数的日期 .

    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)
    
  • 1

    假设您的datetime变量名为date:

    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

    在x个月之后/之前获得下一个日期的一般功能 .

    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)
    
  • 0

    使用python datetime模块向datetime.today()添加六个月的timedelta .

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

    你当然要解决JohannesWeiß提出的问题 - 你的意思是6个月?

  • 3

    这就是我提出的 . 它移动了正确的月数和年数,但忽略了几天(这是我在我的情况下所需要的) .

    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)
    
  • 12

    我用这个函数来改变年份和月份但是保持一天:

    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
    

    你应该写:

    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)
    
  • 2

    我认为做这样的事情而不是手动添加天数会更安全:

    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
    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))
    

相关问题