How to increment datetime by custom months in python without using library
我需要增加日期时间值的月份
1 | next_month = datetime.datetime(mydate.year, mydate.month+1, 1) |
当月份为12时,它变为13并引发错误"月份必须在1到12之间"。(我预计这一年会增加)
我想使用TimeDelta,但它不需要月参数。有relativedelta python包,但我不想只为这个安装它。还有一个使用strtotime的解决方案。
1 2 | time = strtotime(str(mydate)); next_month = date("Y-m-d", strtotime("+1 month", time)); |
我不想从datetime转换为str,然后转换为time,再转换为datetime;因此,它仍然是一个库
有没有人能像使用TimeDelta那样有任何好的简单的解决方案?
使用dateutil的
1 2 3 4 5 6 | 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
警告一句:
注:这需要
1 | sudo apt-get update && sudo apt-get install python-dateutil |
说明:在python中添加月份值
编辑-根据您对需要向下取整的日期的评论,如果下个月的天数较少,下面是一个解决方案:
1 2 3 4 5 6 7 8 9 | 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) |
使用中:
1 2 3 4 5 6 7 8 9 10 | >>> 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) |
另外,如果你不担心小时、分钟和秒,你可以使用
这是我的盐:
1 2 | current = datetime.datetime(mydate.year, mydate.month, 1) next_month = datetime.datetime(mydate.year + (mydate.month / 12), ((mydate.month % 12) + 1), 1) |
快速简单:)
既然没有人提出任何解决方案,下面是到目前为止我是如何解决的
1 2 3 4 5 | year, month= divmod(mydate.month+1, 12) if month == 0: month = 12 year = year -1 next_month = datetime.datetime(mydate.year + year, month, 1) |
使用Monthdelta软件包,它的工作方式与TimeDelta类似,但适用于日历月份而不是天/小时等。
下面是一个例子:
1 2 3 4 5 | from monthdelta import MonthDelta def prev_month(date): """Back one month and preserve day if possible""" return date + MonthDelta(-1) |
将其与DIY方法进行比较:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
要计算当前、上个月和下个月:
1 2 3 4 | 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 |
1 2 3 4 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) |
如果您只想要下个月的第一天:
1 | next = (x.replace(day=1) + timedelta(days=31)).replace(day=1) |
也许可以使用calendar.monthrange()添加当前月份的天数?
1 2 3 4 5 6 7 8 9 | 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) |
这个实现对于使用计费的人可能有一些价值。
如果您正在处理账单,您可能希望得到"下个月的相同日期(如果可能)",而不是"增加1/12的一年"。
令人困惑的是,如果你一直这样做的话,你实际上需要考虑两个值。否则,对于任何超过27天的约会,你都会损失几天,直到你在闰年后的27天结束。
您需要考虑的值:
- 要添加月份的值
- 你开始的那一天
这样,如果你增加一个月,从第31个月减到第30个月,下一个月就可以从第31个月减到第30个月。
我就是这样做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 |
类似于戴夫·韦伯的解决方案,但没有所有复杂的模运算:
1 2 3 4 5 6 7 8 | 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) |
这个怎么样?(不需要任何额外的库)
1 2 3 4 5 | 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) |
有了一些调整和使用TimeDelta,我们开始:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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() |
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日,试试这个:
1 2 3 4 5 6 | 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天),并添加足够的天数以移动到下一个月:
1 2 3 4 5 6 | >>> 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) |
也适用于不同年份:
1 2 3 4 5 | >>> 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日,它将失败:
1 2 3 4 5 6 | >>> 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天(
1 2 3 4 5 6 7 | >>> 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) |
只要用这个:
1 2 3 | import datetime today = datetime.datetime.today() nextMonthDatetime = today + datetime.timedelta(days=(today.max.day - today.day)+1) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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) |
不使用日历的解决方案:
1 2 3 4 5 | 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)) |
这就是我想到的
1 2 3 4 5 6 7 8 | 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)) |
使用时间对象的示例:
1 2 3 4 | 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])) |
我的解决方案非常简单,不需要任何附加模块:
1 2 3 4 5 6 7 | 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 |