Добавьте один месяц к заданной дате (округленный день после) с помощью Python
Я хотел бы добавить один месяц к данной дате
import datetime
dt = datetime.datetime(year=2014, month=5, day=2)
так что я должен сделать
datetime.datetime(year=2014, month=6, day=2)
но с
dt = datetime.datetime(year=2015, month=1, day=31)
Я должен получить
datetime.datetime(year=2015, month=3, day=1)
потому что нет 2015-02-31 (и я хочу, чтобы мой результат был круглым один день после)
некоторые месяцы имеют 31 день, некоторые другие 30, некоторые 29, некоторые 28 !
чтобы добавлять datetime.timedelta
, вероятно, не очень хороший способ сделать (потому что мы не знаем номер дней, чтобы добавить)
я заметил, что у панд есть интересная концепция DateOffset
http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects
но я не нашел Month
смещение, просто MonthBegin
или MonthEnd
Я вижу этот пост Как рассчитать дату через шесть месяцев от текущей даты с помощью модуля datetime Python?
так я пробовал dateutil.relativedelta
но!--14-->
from dateutil.relativedelta import relativedelta
datetime.datetime(year=2015, month=1, day=31)+relativedelta(months=1)
возвращает
datetime.datetime(2015, 2, 28, 0, 0)
так результат был округлен один день до.
есть ли (чистый) способ круглый день после ?
изменить:
Я привел пример с одним месяцем для добавления, но я также хочу иметь возможность добавлять, например : 2 года и 6 месяцев (используя relativedelta(years=2, months=6)
)
4 ответов
можно использовать dateutil.relativedelta.relativedelta
и вручную проверьте datetime.day
атрибут, если исходный день больше, чем новый день, а затем добавить день.
функция, приведенная ниже, принимает datetime
объект и
Это, кажется, работает. Он довольно чистый, но не красивый:
def add_month(now):
try:
then = (now + relativedelta(months=1)).replace(day=now.day)
except ValueError:
then = (now + relativedelta(months=2)).replace(day=1)
return then
for now in [datetime(2015, 1, 20), datetime(2015, 1, 31), datetime(2015, 2, 28)]:
print now, add_month(now)
принты:
2015-01-20 00:00:00 2015-02-20 00:00:00
2015-01-31 00:00:00 2015-03-01 00:00:00
2015-02-28 00:00:00 2015-03-28 00:00:00
Он добавляет один месяц и пытается заменить день на исходный день. Если это удается, это не особый случай. Если это не удается (ValueError), мы должны добавить еще один месяц и перейти к его первому дню.
быстрое решение:
import datetime
import calendar
dt = datetime.datetime(year=2014, month=5, day=2)
d = calendar.monthrange(dt.year,dt.month+1)[1]
print dt+datetime.timedelta(days=d+1)
выход для первого входа (year=2014, month=5, day=2)
:
2014-06-02 00:00:00
выход для второго входа (year=2015, month=1, day=31)
:
2015-03-01 00:00:00
используйте метод bellow:
def datetime_offset_by_months(datetime_origin, n=1):
"""
datetime offset by months
:param datetime_origin: the original datetime
:param n: count of months
:return: after offset datetime
"""
# create a shortcut object for one day
one_day = datetime.timedelta(days=1)
# first use div and mod to determine year cycle
q, r = divmod(datetime_origin.month + n, 12)
# create a datetime_offset
# to be the last day of the target month
datetime_offset = datetime.datetime(
datetime_origin.year + q, r + 1, 1) - one_day
'''
if input date is the last day of this month
then the output date should also be the last
day of the target month, although the day
www.iplaypy.com
may be different.
for example:
datetime_origin = 8.31
datetime_offset = 9.30
'''
if datetime_origin.month != (datetime_origin + one_day).month:
return datetime_offset
'''
if datetime_origin day is bigger than last day of
target month, then, use datetime_offset
for example:
datetime_origin = 10.31
datetime_offset = 11.30
'''
if datetime_origin.day >= datetime_offset.day:
return datetime_offset
'''
then, here, we just replace datetime_offset's day
with the same of datetime_origin, that's ok.
'''
return datetime_offset.replace(day= datetime_origin.day)
использование:
import datetime
now_date = datetime.datetime.now()
off_set_datetime = datetime_offset_by_months(now_date, -2)
print(off_set_datetime)