如何在python中自定义月份增加日期时间而不使用库

我需要增加一个datetime值的月份

next_month = datetime.datetime(mydate.year, mydate.month+1, 1)

当月份为12时,它变成13,并引发错误“month必须在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?

404769 次浏览

通过一些调整和使用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()

由于没有人提出任何解决方案,这里是我目前为止解决的方法

year, month= divmod(mydate.month+1, 12)
if month == 0:
month = 12
year = year -1
next_month = datetime.datetime(mydate.year + year, month, 1)

也许可以使用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)

编辑 -根据你的评论,如果下个月有更少的天,需要四舍五入的日期,这里有一个解决方案:

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并将小时、分钟和秒从源复制到结果。

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

使用time对象的示例:

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

不使用日历的解决方案:

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

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

我的解决方案非常简单,不需要任何额外的模块:

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

这是一个使用dateutil的relativedelta将一个月添加到日期的简短而甜蜜的方法。

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模块。如果你在Linux上,你需要在终端上运行这个命令来安装它。

sudo apt-get update && sudo apt-get install python-dateutil

解释:在python中添加月份值

这是我的盐:

current = datetime.datetime(mydate.year, mydate.month, 1)
next_month = datetime.datetime(mydate.year + int(mydate.month / 12), ((mydate.month % 12) + 1), 1)

简单快捷:)

这个怎么样?(不需要任何额外的库)

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)
def add_month(d,n=1): return type(d)(d.year+(d.month+n-1)/12, (d.month+n-1)%12+1, 1)

我正在寻找解决相关的问题,找到日期的第一个月下一个月,不管的一天在给定的日期。这不是在1个月后的同一天发现的。

所以,如果你只想输入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)

最简单的解决方法是在月底去(我们都知道每个月至少有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)
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)

计算当前、前一个月和下个月的支出:

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

就用这个:

import datetime
today = datetime.datetime.today()
nextMonthDatetime = today + datetime.timedelta(days=(today.max.day - today.day)+1)

这个实现可能对处理账单的人有一定的价值。

如果您正在处理账单,您可能希望得到“下个月相同的日期(如果可能的话)”,而不是“增加一年的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

这是我想到的

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