我正在使用datetime Python模块。我希望从当前日期计算6个月的日期。有人能帮我一下吗?

我想从当前日期生成一个6个月后的日期的原因是为了生成一个回顾日期。如果用户在系统中输入数据,系统将有从输入数据之日起6个月的审查日期。


当前回答

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

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)

其他回答

只需使用timetuple方法提取月份,添加您的月份并构建一个新的dateobject。如果有一个已经存在的方法,我不知道它。

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个月这样的极端情况。:)

我知道这个问题已经有很多答案,但是使用collections.deque和rotate()方法,可以创建一个函数,该函数接受一个datetime对象作为输入,然后输出一个比当前对象晚一个“业务月”的新datetime对象。如果该月的某一天在下个月不存在,则减去1,直到它到达该月的有效日期,然后返回该对象。

import collections
import datetime

def next_month(dt: datetime.datetime):
    month_list = list(range(1, 12 + 1))
    months = collections.deque(month_list)
    while True:
        this_month = list(months)[0]
        if dt.month == this_month:
            break
        months.rotate(-1)
    months.rotate(-1)
    month_plus = list(months)[0]
    for i in range(4):
        try:
            return dt.replace(month=month_plus, day=dt.day - i)
        except ValueError:
            continue

使用itertools.cycle也可以得到相同的结果。

import datetime
import itertools

def next_month(dt: datetime.datetime):
    month_list = list(range(1, 12 + 1))
    month = itertools.cycle(month_list)
    while True:
        if next(month) == dt.month:
            break
    month_plus = next(month)
    for i in range(4):
        try:
            return dt.replace(month=month_plus, day=dt.day - i)
        except ValueError:
            continue

我使用replace()方法并编写了这个递归函数。dt是一个日期时间。datetime对象:

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)

我知道这是6个月,但是如果你要添加一个月,答案在谷歌中显示为“在python中添加月”:

import calendar

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

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

这将计算当前月份的天数,并将它们添加到当前日期,如果您在日期上迭代,则使用365/12将AD年的1/12会导致短/长月份出现问题。

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

#!/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
$