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

2025-01-03 14:22:00
admin
原创
265
摘要:问题描述:我正在使用 datetime Python 模块。我希望计算从当前日期开始 6 个月后的日期。有人能帮我做这件事吗?我想要生成距当前日期 6 个月的日期的原因是为了生成审核日期。如果用户将数据输入系统,则审核日期将从他们输入数据之日起 6 个月。解决方案 1:我发现这个解决方案很好。(这使用了pyt...

问题描述:

我正在使用 datetime Python 模块。我希望计算从当前日期开始 6 个月后的日期。有人能帮我做这件事吗?

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


解决方案 1:

我发现这个解决方案很好。(这使用了python-dateutil 扩展)

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 个月是什么意思。

  1. 使用自然月份:

inc = 6
year = year + (month + inc - 1) // 12
month = (month + inc - 1) % 12 + 1
  1. 按照银行家的定义,6*30:

date += datetime.timedelta(6 * 30)

解决方案 3:

使用 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

解决方案 4:

因此,这里有一个我发现很有用的例子,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)

解决方案 5:

Python 可以使用 datautil 包来实现这一点,请参见下面的示例

不仅限于此,您还可以同时传递天数、月份和年份的组合。

import datetime
from dateutil.relativedelta import relativedelta

# subtract months
proc_dt = datetime.date(2021,8,31)
proc_dt_minus_3_months = proc_dt + relativedelta(months=-3)
print(proc_dt_minus_3_months)

# add months
proc_dt = datetime.date(2021,8,31)
proc_dt_plus_3_months = proc_dt + relativedelta(months=+3)
print(proc_dt_plus_3_months)

# subtract days:
proc_dt = datetime.date(2021,8,31)
proc_dt_minus_3_days = proc_dt + relativedelta(days=-3)
print(proc_dt_minus_3_days)

# add days days:
proc_dt = datetime.date(2021,8,31)
proc_dt_plus_3_days = proc_dt + relativedelta(days=+3)
print(proc_dt_plus_3_days)

# subtract years:
proc_dt = datetime.date(2021,8,31)
proc_dt_minus_3_years = proc_dt + relativedelta(years=-3)
print(proc_dt_minus_3_years)

# add years:
proc_dt = datetime.date(2021,8,31)
proc_dt_plus_3_years = proc_dt + relativedelta(years=+3)
print(proc_dt_plus_3_years)

结果:

2021-05-31

2021-11-30

2021-08-28

2021-09-03

2018-08-31

2024-08-31

解决方案 6:

这并没有回答具体的问题(datetime仅使用),但考虑到其他人建议使用不同的模块,这里有一个使用的解决方案pandas

import datetime as dt
import pandas as pd

date = dt.date.today() - \n       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

在闰年也能按预期工作

date = dt.datetime(2019,8,29) - \n       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

解决方案 7:

对于月初到月末的计算:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

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

解决方案 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  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

但是……这不能解决 1 月 31 日 + 一个月的问题。所以我们回到 OP - 你说的增加一个月是什么意思?一个解决方案是回溯直到找到一个有效的日期,因为大多数人会假设 1 月的最后一天加上一个月等于 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)>>> 

解决方案 9:

你说的“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的更多信息

解决方案 10:

没有直接的方法可以使用 Python 的日期时间来做到这一点。

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

解决方案 11:

我知道这是 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,如果您对日期进行迭代,则会导致短月份/长月份出现问题。

解决方案 12:

只需使用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 个月等极端情况。:)

解决方案 13:

使用 Python 标准库(即不使用dateutil或其他库)并解决“2 月 31 日”问题:

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

解决方案 14:

Dateutil 包已实现此类功能。但请注意,正如其他人已经指出的那样,这将是幼稚的

解决方案 15:

我有一个更好的方法来解决“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)

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

解决方案 16:

快速建议是Arrow

pip 安装箭头

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

解决方案 17:

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)

解决方案 18:

修改了 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)

解决方案 19:

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

解决方案 20:

修改了 Johannes Wei 的答案,其中 1new_month = 121。这对我来说非常有效。月份可以是正数也可以是负数。

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)

解决方案 21:

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    %s    %s" %(start_date, end_date, m))

解决方案 22:

重新整理了 user417751 的早期答案。可能不是那么 Python 化,但它处理了不同的月份长度和闰年。在本例中,2012 年 1 月 31 日 + 1 个月 = 2012 年 2 月 29 日。

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)

解决方案 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")

解决方案 24:

从此答案中,请参阅parsedatetime。代码示例如下。更多详细信息:包含许多自然语言 -> YYYY-MM-DD 转换示例的单元测试,以及明显的parsedatetime 转换挑战/错误。

#!/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 + ', ' + \n                              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
$ 

解决方案 25:

这个怎么样?不使用其他库(dateutil)或timedelta?根据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/2所以或6*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

我希望这对你有帮助。

解决方案 26:

这里有一个例子,允许用户决定如何返回日期大于月份天数的日期。

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \n        '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 \n            endOfMonthBehaviour == 'RoundOut' and months < 0 or \n            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \n            endOfMonthBehaviour == 'RoundOut' and months > 0 or \n            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)

解决方案 27:

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

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)

解决方案 28:

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

从日期时间导入日期

def after_month(给定日期,月份):
    yyyy = int(((给定日期.年份 * 12 + 给定日期.月份) + 月份)/12)
    mm = int(((给定日期.年份 * 12 + 给定日期.月份) + 月份)%12)

    如果 mm == 0:
        yyyy -= 1
        毫米 = 12
    返回给定日期.replace(年份=yyyy,月份=mm)


如果 __name__ == "__main__":
    今天 = 日期.今天()
    打印(今天)

    对于[-12,-1,0,1,2,12,20]中的毫米:
        下一日期 = 后月 (今天,月)
        打印(下一个日期)

解决方案 29:

我迟到了,但是

查看 Ken Reitz Maya 模块,

https://github.com/kennethreitz/maya

类似这样的事情可能会对你有帮助,只需将 hours=1 更改为 days=1 或 years=1

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

解决方案 30:

“python-dateutil”(外部扩展)是一个很好的解决方案,但你可以用内置的 Python 模块(datetime 和 datetime)来实现

我编写了一个简短而简单的代码来解决它(处理年、月、日)

(运行:Python 3.8.2)

from datetime import datetime
from calendar import monthrange

# Time to increase (in months)
inc = 12

# Returns mod of the division for 12 (months)
month = ((datetime.now().month + inc) % 12) or 1

# Increase the division by 12 (months), if necessary (+ 12 months increase)
year = datetime.now().year + int((month + inc) / 12)

# (IF YOU DON'T NEED DAYS,CAN REMOVE THE BELOW CODE)
# Returns the same day in new month, or the maximum day of new month
day = min(datetime.now().day,monthrange(year, month)[1])

print("Year: {}, Month: {}, Day: {}".format(year, month, day))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用