Как рассчитать дату через шесть месяцев с текущей даты с помощью модуля datetime Python?
Я использую модуль datetime Python. Я ищу, чтобы вычислить дату 6 месяцев от текущей даты. Может кто-нибудь помочь мне сделать это?
причина, по которой я хочу создать дату 6 месяцев с текущей даты, заключается в создании даты обзора. Если пользователь вводит данные в систему, он будет иметь дату обзора 6 месяцев с даты ввода данных.
30 ответов:
Я нашел это решение, чтобы быть хорошим. (Это использует python-dateutil extension)
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)
Ну, это зависит от того, что вы подразумеваете под 6 месяцами с текущей даты.
используя природный месяцев:
(day, month, year) = (day, (month+6)%12, year+(month+6)/12)используя определение банкира, 6*30:
date += datetime.timedelta(6*30)
для расчета от месяца к месяцу:
from datetime import timedelta from dateutil.relativedelta import relativedelta end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)
что вы подразумеваете под '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
это решение работает правильно для декабря, что большинство ответов на этой странице не делают. Вам нужно сначала переместить месяцы из базы 1 (т. е. Jan = 1) в базу 0 (т. е. Jan = 0) перед использованием модуля ( % ) или целочисленного деления ( / / ), иначе ноябрь ( 11) плюс 1 месяц дает вам 12, что при нахождении остатка (12% 12 ) дает 0.
(и не предлагайте "(месяц % 12) + 1" или Октябрь + 1 = декабрь!)
def AddMonths(d,x): newmonth = ((( d.month - 1) + x ) % 12 ) + 1 newyear = d.year + ((( d.month - 1) + x ) / 12 ) return datetime.date( newyear, newmonth, d.day)однако ... Это не учитывает проблему, как 31 января + один месяц. Итак, мы возвращаемся к OP-что вы имеете в виду, добавив месяц? Один soln-вернуться назад, пока вы не доберетесь до действительного дня, учитывая, что большинство людей будут предполагать, что последний день января плюс один месяц равен последнему дню февраля. Это будет работать и на отрицательных числах месяцев. Доказательство:
>>> 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)>>>
нет прямого способа сделать это с помощью Python datetime.
Проверьте тип relativedelta в python-dateutil. Это позволяет указать интервал времени в месяцах.
Я знаю, что это было в течение 6 месяцев, однако ответ показывает в google для "добавления месяцев в python", если вы добавляете один месяц:
import calendar date = datetime.date.today() //Or your date datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])это будет считать дни в текущем месяце и добавить их к текущей дате, используя 365/12 будет объявление 1/12 года может вызвать проблемы для коротких / длинных месяцев, если ваш итерации по дате.
Dateutil package реализация такой функциональности. Но знайте, что это будет наивный, как указал уже.
вот пример
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)
просто использовать 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, day)API немного неуклюж, но работает в качестве примера. Также, очевидно, не будет работать на угловых случаях, таких как 2008-01-31 + 1 месяц. :)
использование стандартных библиотек Python, т. е. без
dateutilили другие, и решение проблемы "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))
У меня есть лучший способ решить проблему 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)Я думаю, что он также работает с отрицательными числами (чтобы вычесть месяцы), но я не проверял это очень много.
класс QDate PyQt4 имеет функцию 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)
изменен 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)
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)))
как насчет этого? Не используя другую библиотеку (
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)Я надеюсь, вы найдете это полезным.
Я решил эту проблему так:
import calendar from datetime import datetime moths2add = 6 now = datetime.now() current_year = now.year current_month = now.month #count days in months you want to add using calendar module days = sum( [calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)] ) print now + days
модифицированный ответ Йоханнеса Вея в случае 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)
еще одно решение-надеюсь, кому-то понравится:
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")
С ответ см. parsedatetime. Ниже приведен пример кода. Более детально: модульный тест со многими примерами преобразования естественного языка- > гггг-ММ-ДД, и очевидно проблемы преобразования 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 + ', ' + \ 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 $
учитывая, что ваша переменная datetime называется date:
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)
общая функция для получения следующей даты после / до x месяцев.
from datetime import date def after_month(given_date, month): yyyy = int(((given_date.year * 12 + given_date.month) + month)/12) mm = int(((given_date.year * 12 + given_date.month) + month)%12) if mm == 0: yyyy -= 1 mm = 12 return given_date.replace(year=yyyy, month=mm) if __name__ == "__main__": today = date.today() print(today) for mm in [-12, -1, 0, 1, 2, 12, 20 ]: next_date = after_month(today, mm) print(next_date)
С 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
используйте модуль python datetime, чтобы добавить timedelta из шести месяцев в datetime.сегодняшний день. )(
http://docs.python.org/library/datetime.html
вам, конечно, придется решить вопрос, поднятый Йоханнесом Вайсом-что do вы имеете в виду 6 месяцев?
вот что я придумал. Он перемещает правильное количество месяцев и лет, но игнорирует дни (что было мне нужно в моей ситуации).
import datetime month_dt = 4 today = datetime.date.today() y,m = today.year, today.month m += month_dt-1 year_dt = m//12 new_month = m%12 new_date = datetime.date(y+year_dt, new_month+1, 1)
Я использую эту функцию, чтобы изменить год и месяц, но держать дня:
def replace_month_year(date1, year2, month2): try: date2 = date1.replace(month = month2, year = year2) except: date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1) return date2вы должны написать:
new_year = my_date.year + (my_date.month + 6) / 12 new_month = (my_date.month + 6) % 12 new_date = replace_month_year(my_date, new_year, new_month)
Я думаю, что было бы безопаснее сделать что-то вроде этого, а не вручную добавлять дни:
import datetime today = datetime.date.today() def addMonths(dt, months = 0): new_month = months + dt.month year_inc = 0 if new_month>12: year_inc +=1 new_month -=12 return dt.replace(month = new_month, year = dt.year+year_inc) newdate = addMonths(today, 6)
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\t%s\t%s" %(start_date, end_date, m))
переработать более ранний ответ user417751. Может быть, не так питонский способ, но он заботится о разных длинах месяцев и високосных годах. В этом случае 31 января 2012 года + 1 месяц = 29 февраля 2012 года.
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)
Comments