Попробуй это:
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, [31,
29 if y%4==0 and not y%400==0 else 28,31,30,31,30,31,31,30,31,30,31][m-1])
return date.replace(day=d,month=m, year=y)
>>> for m in range(-12, 12):
print(monthdelta(datetime.now(), m))
2009-08-06 16:12:27.823000
2009-09-06 16:12:27.855000
2009-10-06 16:12:27.870000
2009-11-06 16:12:27.870000
2009-12-06 16:12:27.870000
2010-01-06 16:12:27.870000
2010-02-06 16:12:27.870000
2010-03-06 16:12:27.886000
2010-04-06 16:12:27.886000
2010-05-06 16:12:27.886000
2010-06-06 16:12:27.886000
2010-07-06 16:12:27.886000
2010-08-06 16:12:27.901000
2010-09-06 16:12:27.901000
2010-10-06 16:12:27.901000
2010-11-06 16:12:27.901000
2010-12-06 16:12:27.901000
2011-01-06 16:12:27.917000
2011-02-06 16:12:27.917000
2011-03-06 16:12:27.917000
2011-04-06 16:12:27.917000
2011-05-06 16:12:27.917000
2011-06-06 16:12:27.933000
2011-07-06 16:12:27.933000
>>> monthdelta(datetime(2010,3,30), -1)
datetime.datetime(2010, 2, 28, 0, 0)
>>> monthdelta(datetime(2008,3,30), -1)
datetime.datetime(2008, 2, 29, 0, 0)
Править. Исправлено также и для дня.
Изменить См. Также ответ из недоумения, который указывает на более простой расчет для d
:
d = min(date.day, calendar.monthrange(y, m)[1])
((date.month+delta-1) % 12)+1
работает и означает, чтоif not m: m = 12
банка будет удаленаdt - timedelta(days=dt.day)
первоначальной формулировкой, хотя это звучало так, как будто они хотели вычесть произвольное количество месяцев, а это немного сложнее.29 if y%4==0 and (not y%100==0 or y%400 == 0) else 28
. например, 1600 - високосный год, а 1700 - нетВы можете использовать сторонний
dateutil
модуль ( здесь запись PyPI ).вывод:
источник
month
иmonths
dateutil. Вычитание с параметромmonth
не работает, ноmonths
работаетIn [23]: created_datetime__lt - relativedelta(months=1) Out[23]: datetime.datetime(2016, 11, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>) In [24]: created_datetime__lt - relativedelta(month=1) Out[24]: datetime.datetime(2016, 1, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>)
months
будет иметь значение 1 месяц. Использованиеmonth
установит месяц на 1 (например, январь), независимо от месяца ввода.После изменения исходного вопроса на «любой объект datetime в предыдущем месяце» вы можете сделать это довольно легко, вычтя 1 день из первого числа месяца.
источник
dt.replace(day=1) - timedelta(1)
dt - timedelta(days=dt.day)
Вариант ответа Дункана (у меня недостаточно репутации для комментариев), в котором используется calendar.monthrange, чтобы значительно упростить вычисление последнего дня месяца:
Информация о месячном диапазоне от Получить последний день месяца в Python
источник
Векторизованное решение pandas очень простое:
df['date'] - pd.DateOffset(months=1)
источник
pandas
. Спасибо!Каким должен быть результат, если вычесть месяц, скажем, из даты 30 марта? В этом проблема добавления или вычитания месяцев: месяцы имеют разную длину! В некоторых приложениях в таких случаях уместно исключение, в других можно использовать «последний день предыдущего месяца» (но это действительно сумасшедшая арифметика, когда вычитание месяца и добавление месяца в целом не является бездействием!) , в других случаях вы захотите сохранить в дополнение к дате некоторое указание на этот факт, например, «Я говорю 28 февраля, но мне действительно нужно 30 февраля, если он существует», чтобы добавить или вычесть еще один месяц к который может снова все исправить (а последнее, очевидно, требует специального класса, содержащего данные плюс что-то еще).
Не может быть реального решения, приемлемого для всех приложений, и вы не сказали нам, какие потребности вашего конкретного приложения необходимы для семантики этой жалкой операции, так что мы не можем предоставить больше помощи здесь.
источник
datetime
modules предполагает, что день составляет ровно 24 часа (без дополнительных секунд)Я думаю, что простой способ - использовать DateOffset из Pandas следующим образом:
Результатом будет объект datetime
источник
Если вам нужен любой день последнего месяца, самое простое, что вы можете сделать, - это вычесть количество дней из текущей даты, что даст вам последний день предыдущего месяца.
Например, начиная с любой даты:
Вычитая дни текущей даты, получаем:
Этого достаточно для вашей упрощенной потребности в любой день последнего месяца.
Но теперь, когда он у вас есть, вы также можете получить любой день месяца, включая тот же день, с которого вы начали (т.е. более или менее то же самое, что и вычитание месяца):
Конечно, вам нужно быть осторожным с 31-м числом 30-дневного месяца или с днями, пропущенными с февраля (и позаботиться о високосных годах), но это также легко сделать:
источник
Я использую это для государственных финансовых лет, когда четвертый квартал начинается 1 октября. Обратите внимание, я конвертирую дату в четверти и также отменяю ее.
источник
Вот код для этого. Сам не пробовал ...
источник
Учитывая кортеж (год, месяц), где месяц идет от 1 до 12, попробуйте следующее:
Предполагается, что в году 12 месяцев.
источник
источник
Я использовал следующий код, чтобы вернуться на n месяцев с определенной даты:
Например: дата ввода = 28/12/2015 Вычислить дату за 6 месяцев до даты.
I) РАССЧИТАТЬ МЕСЯЦ: На этом шаге вы получите start_date как 30.06.2015.
Обратите внимание, что после шага вычисления месяца вы получите последний день требуемого месяца.
II) РАСЧЕТ ДНЯ: Условие if (start_date.day> your_date.day) проверяет, присутствует ли день из input_date в требуемом месяце. Это обрабатывает условие, когда дата ввода 31 (или 30), а в требуемом месяце меньше 31 (или 30 в случае февраля) дня. Он также обрабатывает случай високосного года (за февраль). После этого шага вы получите результат 28.06.2015.
Если это условие не выполняется, start_date остается последней датой предыдущего месяца. Итак, если вы укажете 31/12/2015 в качестве даты ввода и хотите, чтобы дата была 6 месяцев назад, это даст вам 30/06/2015
источник
Вы можете использовать приведенную ниже функцию, чтобы получить дату до / после X месяца.
источник
Думаю, ответ вполне читаем:
источник
Один лайнер ?
previous_month_date = (current_date - datetime.timedelta(days=current_date.day+1)).replace(day=current_date.day)
источник
Самый простой способ, который я пробовал только что
источник
Некоторое время назад я наткнулся на следующий алгоритм, который очень хорошо работает для увеличения и уменьшения месяцев на a
date
илиdatetime
.ПРЕДОСТЕРЕЖЕНИЕ : это не удастся, если
day
не будет доступно в новом месяце. Я использую это на объектах даты гдеday == 1
всегда.Python 3.x:
Для Python 2.7 измените значение
//12
на только/12
поскольку подразумевается целочисленное деление.Я недавно использовал это в файле значений по умолчанию, когда скрипт начал получать эти полезные глобальные переменные:
источник
Простое решение, никаких специальных библиотек не требуется.
источник
Вы можете сделать это двумя строчками:
помните импорт
источник