如何在不使用库的情况下在 python 中按自定义月份增加日期时间[重复]
- 2025-03-04 08:27:00
- admin 原创
- 70
问题描述:
我需要增加日期时间值的月份
next_month = datetime.datetime(mydate.year, mydate.month+1, 1)
当月份为 12 时,它变为 13,并引发错误“月份必须在 1..12”。 (我预计年份会增加)
我想使用 timedelta,但它不需要月份参数。有relativedelta python 包,但我不想只为此安装它。还有一个使用strtotime的解决方案。
time = strtotime(str(mydate));
next_month = date("Y-m-d", strtotime("+1 month", time));
我不想从 datetime 转换为 str,然后转换为 time,然后再转换为 datetime;因此,它仍然是一个库
有没有人有像使用 timedelta 一样好的、简单的解决方案?
解决方案 1:
这是一个使用dateutilrelativedelta
向日期添加月份的简短而有效的方法。
from datetime import datetime
from dateutil.relativedelta import relativedelta
date_after_month = datetime.today()+ relativedelta(months=1)
print('Today: ',datetime.today().strftime('%d/%m/%Y'))
print('After Month:', date_after_month.strftime('%d/%m/%Y'))
Today: 01/03/2013
After Month: 01/04/2013
提醒一句:relativedelta(months=1)
和relativedelta(month=1)
的含义不同。 经过month=1
将替换原始日期中的月份为 1 月,而经过months=1
将在原始日期上添加一个月。
注意:这需要python-dateutil
模块。使用此命令行安装:
pip install --user python-dateutil
解释:在 Python 中添加月份值
解决方案 2:
编辑- 根据您对下个月天数较少时需要将日期向下舍入的评论,这里有一个解决方案:
import datetime
import calendar
def add_months(sourcedate, months):
month = sourcedate.month - 1 + months
year = sourcedate.year + month // 12
month = month % 12 + 1
day = min(sourcedate.day, calendar.monthrange(year,month)[1])
return datetime.date(year, month, day)
使用中:
>>> somedate = datetime.date.today()
>>> somedate
datetime.date(2010, 11, 9)
>>> add_months(somedate,1)
datetime.date(2010, 12, 9)
>>> add_months(somedate,23)
datetime.date(2012, 10, 9)
>>> otherdate = datetime.date(2010,10,31)
>>> add_months(otherdate,1)
datetime.date(2010, 11, 30)
另外,如果您不担心小时、分钟和秒,则可以使用date
而不是datetime
。如果您担心小时、分钟和秒,则需要修改我的代码以使用datetime
并将小时、分钟和秒从源复制到结果。
解决方案 3:
这是我的盐:
current = datetime.datetime(mydate.year, mydate.month, 1)
next_month = datetime.datetime(mydate.year + int(mydate.month / 12), ((mydate.month % 12) + 1), 1)
快速又简单:)
解决方案 4:
由于没有人提出任何解决方案,以下是我迄今为止的解决方法
year, month= divmod(mydate.month+1, 12)
if month == 0:
month = 12
year = year -1
next_month = datetime.datetime(mydate.year + year, month, 1)
解决方案 5:
from datetime import timedelta
try:
next = (x.replace(day=1) + timedelta(days=31)).replace(day=x.day)
except ValueError: # January 31 will return last day of February.
next = (x + timedelta(days=31)).replace(day=1) - timedelta(days=1)
如果您只想要下个月的第一天:
next = (x.replace(day=1) + timedelta(days=31)).replace(day=1)
解决方案 6:
使用monthdelta包,它的工作方式与 timedelta 一样,但针对的是日历月而不是天/小时/等等。
以下是一个例子:
from monthdelta import MonthDelta
def prev_month(date):
"""Back one month and preserve day if possible"""
return date + MonthDelta(-1)
将其与 DIY 方法进行比较:
def prev_month(date):
"""Back one month and preserve day if possible"""
day_of_month = date.day
if day_of_month != 1:
date = date.replace(day=1)
date -= datetime.timedelta(days=1)
while True:
try:
date = date.replace(day=day_of_month)
return date
except ValueError:
day_of_month -= 1
解决方案 7:
计算当前月份、上个月和下个月:
import datetime
this_month = datetime.date.today().month
last_month = datetime.date.today().month - 1 or 12
next_month = (datetime.date.today().month + 1) % 12 or 12
解决方案 8:
这个怎么样?(不需要任何额外的库)
from datetime import date, timedelta
from calendar import monthrange
today = date.today()
month_later = date(today.year, today.month, monthrange(today.year, today.month)[1]) + timedelta(1)
解决方案 9:
也许可以使用 calendar.monthrange() 添加当前月份的天数?
import calendar, datetime
def increment_month(when):
days = calendar.monthrange(when.year, when.month)[1]
return when + datetime.timedelta(days=days)
now = datetime.datetime.now()
print 'It is now %s' % now
print 'In a month, it will be %s' % increment_month(now)
解决方案 10:
最简单的解决方案是在月底(我们始终知道月份至少有 28 天)并添加足够的天数以移动到下个月:
>>> from datetime import datetime, timedelta
>>> today = datetime.today()
>>> today
datetime.datetime(2014, 4, 30, 11, 47, 27, 811253)
>>> (today.replace(day=28) + timedelta(days=10)).replace(day=today.day)
datetime.datetime(2014, 5, 30, 11, 47, 27, 811253)
也适用于年份:
>>> dec31
datetime.datetime(2015, 12, 31, 11, 47, 27, 811253)
>>> today = dec31
>>> (today.replace(day=28) + timedelta(days=10)).replace(day=today.day)
datetime.datetime(2016, 1, 31, 11, 47, 27, 811253)
请记住,不能保证下个月会有同一天,例如从 1 月 31 日移动到 2 月 31 日就会失败:
>>> today
datetime.datetime(2016, 1, 31, 11, 47, 27, 811253)
>>> (today.replace(day=28) + timedelta(days=10)).replace(day=today.day)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: day is out of range for month
因此,如果您需要移动到下个月的第一天,这是一个有效的解决方案,因为您始终知道下个月有第 1天( .replace(day=1)
)。否则,要移动到最后一天,您可能需要使用:
>>> today
datetime.datetime(2016, 1, 31, 11, 47, 27, 811253)
>>> next_month = (today.replace(day=28) + timedelta(days=10))
>>> import calendar
>>> next_month.replace(day=min(today.day,
calendar.monthrange(next_month.year, next_month.month)[1]))
datetime.datetime(2016, 2, 29, 11, 47, 27, 811253)
解决方案 11:
与 Dave Webb 的解决方案在理想上类似,但没有所有那些棘手的模数算法:
import datetime, calendar
def increment_month(date):
# Go to first of this month, and add 32 days to get to the next month
next_month = date.replace(day=1) + datetime.timedelta(32)
# Get the day of month that corresponds
day = min(date.day, calendar.monthrange(next_month.year, next_month.month)[1])
return next_month.replace(day=day)
解决方案 12:
我一直在寻找解决相关问题的方法,即查找下个月第一天的日期,而不管给定日期是哪天。但这种方法无法找到一个月后的同一天。
因此,如果您只想输入 2014 年 12 月 12 日(或 12 月的任何一天)并返回 2015 年 1 月 1 日,请尝试以下操作:
import datetime
def get_next_month(date):
month = (date.month % 12) + 1
year = date.year + (date.month + 1 > 12)
return datetime.datetime(year, month, 1)
解决方案 13:
对于从事计费工作的人来说,此实施可能具有一定的价值。
如果您正在处理帐单,您可能希望获得“下个月的同一日期(如果可能)”,而不是“增加一年的 1/12”。
令人困惑的是,如果你连续这样做,你实际上需要考虑两个值。否则,对于 27 日之后的任何日期,你都会继续丢失几天,直到闰年后达到 27 日。
您需要考虑的价值观:
您想要添加一个月的值
你开始的那一天
这样,如果您在增加一个月时从 31 号降到 30 号,那么在包含该日期的下一个月份,您将被重新调整回 31 号。
我是这样做的:
def closest_date_next_month(year, month, day):
month = month + 1
if month == 13:
month = 1
year = year + 1
condition = True
while condition:
try:
return datetime.datetime(year, month, day)
except ValueError:
day = day-1
condition = day > 26
raise Exception('Problem getting date next month')
paid_until = closest_date_next_month(
last_paid_until.year,
last_paid_until.month,
original_purchase_date.day) # The trick is here, I'm using the original date, that I started adding from, not the last one
解决方案 14:
好了,经过一些调整并使用timedelta,我们可以开始:
from datetime import datetime, timedelta
def inc_date(origin_date):
day = origin_date.day
month = origin_date.month
year = origin_date.year
if origin_date.month == 12:
delta = datetime(year + 1, 1, day) - origin_date
else:
delta = datetime(year, month + 1, day) - origin_date
return origin_date + delta
final_date = inc_date(datetime.today())
print final_date.date()
解决方案 15:
不使用日历的解决方案:
def add_month_year(date, years=0, months=0):
year, month = date.year + years, date.month + months + 1
dyear, month = divmod(month - 1, 12)
rdate = datetime.date(year + dyear, month + 1, 1) - datetime.timedelta(1)
return rdate.replace(day = min(rdate.day, date.day))
解决方案 16:
def add_month(d,n=1): return type(d)(d.year+(d.month+n-1)/12, (d.month+n-1)%12+1, 1)
解决方案 17:
这就是我想出的
from calendar import monthrange
def same_day_months_after(start_date, months=1):
target_year = start_date.year + ((start_date.month + months) / 12)
target_month = (start_date.month + months) % 12
num_days_target_month = monthrange(target_year, target_month)[1]
return start_date.replace(year=target_year, month=target_month,
day=min(start_date.day, num_days_target_month))
解决方案 18:
def month_sub(year, month, sub_month):
result_month = 0
result_year = 0
if month > (sub_month % 12):
result_month = month - (sub_month % 12)
result_year = year - (sub_month / 12)
else:
result_month = 12 - (sub_month % 12) + month
result_year = year - (sub_month / 12 + 1)
return (result_year, result_month)
def month_add(year, month, add_month):
return month_sub(year, month, -add_month)
>>> month_add(2015, 7, 1)
(2015, 8)
>>> month_add(2015, 7, 20)
(2017, 3)
>>> month_add(2015, 7, 12)
(2016, 7)
>>> month_add(2015, 7, 24)
(2017, 7)
>>> month_add(2015, 7, -2)
(2015, 5)
>>> month_add(2015, 7, -12)
(2014, 7)
>>> month_add(2015, 7, -13)
(2014, 6)
解决方案 19:
只需使用这个:
import datetime
today = datetime.datetime.today()
nextMonthDatetime = today + datetime.timedelta(days=(today.max.day - today.day)+1)
解决方案 20:
使用时间对象的示例:
start_time = time.gmtime(time.time()) # start now
#increment one month
start_time = time.gmtime(time.mktime([start_time.tm_year, start_time.tm_mon+1, start_time.tm_mday, start_time.tm_hour, start_time.tm_min, start_time.tm_sec, 0, 0, 0]))
解决方案 21:
我的解决方案非常简单,不需要任何额外的模块:
def addmonth(date):
if date.day < 20:
date2 = date+timedelta(32)
else :
date2 = date+timedelta(25)
date2.replace(date2.year, date2.month, day)
return date2
扫码咨询,免费领取项目管理大礼包!