Python сколько дней до конца месяца

Получить последний день месяца в Python

Есть ли способ использовать стандартную библиотеку Python, чтобы легко определить (например, один вызов функции) последний день данного месяца? Если стандартная библиотека не поддерживает это, поддерживает ли этот пакет dateutil?

Я единственный, кто подумал, что вы спрашиваете о последнем дне Монти Пайтона? : D [20081124 Перенесено из ответа в комментарий — оригинальный ответ был опубликован до того, как система комментариев была введена в SO]

29 ответов

Я не заметил этого раньше, когда смотрел документацию для модуля календаря, но метод под названием monthrange предоставляет следующую информацию:

monthrange (год, месяц)
Возвращает день недели первого дня месяца и количество дней в месяце, за указанный год и месяц.

>>> import calendar >>> calendar.monthrange(2002,1) (1, 31) >>> calendar.monthrange(2008,2) (4, 29) >>> calendar.monthrange(2100,2) (0, 28) 
calendar.monthrange(year, month)[1] 

кажется самым простым способом.

Чтобы быть понятным, monthrange также поддерживает високосные годы:

>>> from calendar import monthrange >>> monthrange(2012, 2) (2, 29) 

Мой предыдущий ответ по-прежнему работает, но явно субоптимален.

Это не правильный ответ на оригинальный вопрос! Что делать, если последний день месяца — суббота / солнце.

@mahdi: это правильно, второе число — это «число дней в месяце» == «последний день», независимо от того, что это за день.

@ sword1st, я вижу 28 как ответ, который является правильным, используя правила для григорианского календаря

Если вы не хотите импортировать модуль calendar , простая двухступенчатая функция также может быть:

import datetime def last_day_of_month(any_day): next_month = any_day.replace(day=28) + datetime.timedelta(days=4) # this will never fail return next_month - datetime.timedelta(days=next_month.day) 
>>> for month in range(1, 13): . print last_day_of_month(datetime.date(2012, month, 1)) . 2012-01-31 2012-02-29 2012-03-31 2012-04-30 2012-05-31 2012-06-30 2012-07-31 2012-08-31 2012-09-30 2012-10-31 2012-11-30 2012-12-31 

EDIT: см. ответ @Blair Conrad для более чистого решения

>>> import datetime >>> datetime.date (2000, 2, 1) - datetime.timedelta (days = 1) datetime.date(2000, 1, 31) >>> 

Я бы на самом деле назвал это чище, за исключением того факта, что он не работает в декабре, когда сегодня today.month + 1 == 13 и вы получите ValueError .

EDIT: см. мой другой ответ. Он имеет лучшую реализацию, чем эта, которую я оставляю здесь на случай, если кто-то заинтересован в том, как можно «раскрутить свой» калькулятор.

@Джон Милликин дает хороший ответ с дополнительным усложнением расчета первого дня следующего месяца.

Ниже не особенно изящно, но чтобы выяснить последний день месяца, в котором проживает какая-либо дата, вы можете попробовать:

def last_day_of_month(date): if date.month == 12: return date.replace(day=31) return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1) >>> last_day_of_month(datetime.date(2002, 1, 17)) datetime.date(2002, 1, 31) >>> last_day_of_month(datetime.date(2002, 12, 9)) datetime.date(2002, 12, 31) >>> last_day_of_month(datetime.date(2008, 2, 14)) datetime.date(2008, 2, 29) 

Да, но я был сбит с толку, я выглядел примерно так: start_date = date (datetime.now (). Year, datetime.now (). Month, 1)

Ах. today = datetime.date.today(); start_date = today.replace(day=1) . Вам следует избегать повторного вызова datetime.now, если вы звоните ему до полуночи 31 декабря, а затем сразу после полуночи. Вы получите 2016-01-01 вместо 2016-12-01 или 2017-01-01.

Это очень просто для понимания и возвращает экземпляр datetime, который может быть полезен во многих случаях. Другое преимущество заключается в том, что он работает, если входная date является экземпляром datetime.date , datetime.datetime а также pandas.Timestamp .

Это довольно легко с dateutil.relativedelta (пакет python-datetutil для pip). day=31 всегда будет возвращать последний день месяца.

from datetime import datetime from dateutil.relativedelta import relativedelta date_in_feb = datetime.datetime(2013, 2, 21) print datetime.datetime(2013, 2, 21) + relativedelta(day=31) # End-of-month >>> datetime.datetime(2013, 2, 28, 0, 0) 

Мне лично нравится относительная дельта (месяцы = + 1, секунды = -1), кажется более очевидным, что происходит

Используя relativedelta , вы получите последнюю дату месяца следующим образом:

from dateutil.relativedelta import relativedelta last_date_of_month = datetime(mydate.year,mydate.month,1)+relativedelta(months=1,days=-1) 

Идея состоит в том, чтобы получить первый день месяца и использовать relativedelta для перехода на 1 месяц вперед и 1 день назад, чтобы вы получили последний день месяца, который вы хотели.

Другим решением было бы сделать что-то вроде этого:

from datetime import datetime def last_day_of_month(year, month): """ Work out the last day of the month """ last_days = [31, 30, 29, 28, 27] for i in last_days: try: end = datetime(year, month, i) except ValueError: continue else: return end.date() return None 

И используйте функцию следующим образом:

>>> >>> last_day_of_month(2008, 2) datetime.date(2008, 2, 29) >>> last_day_of_month(2009, 2) datetime.date(2009, 2, 28) >>> last_day_of_month(2008, 11) datetime.date(2008, 11, 30) >>> last_day_of_month(2008, 12) datetime.date(2008, 12, 31) 
from datetime import timedelta (any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1) 

Оно работает. any_day — 31 января, мы заменяем день на 1, поэтому 1 января, добавляем 32 дня, мы получаем 2 февраля, снова заменяем на день = 1 и получаем 1 февраля. Вычтите один день, и мы получим 31 января. Я не вижу в чем проблема. Какой у тебя день?

>>> import datetime >>> import calendar >>> date = datetime.datetime.now() >>> print date 2015-03-06 01:25:14.939574 >>> print date.replace(day = 1) 2015-03-01 01:25:14.939574 >>> print date.replace(day = calendar.monthrange(date.year, date.month)[1]) 2015-03-31 01:25:14.939574 

если вы хотите использовать внешнюю библиотеку, посмотрите http://crsmithdev.com/arrow/

Вы можете получить последний день месяца с помощью:

import arrow arrow.utcnow().ceil('month').date() 

Это возвращает объект даты, который вы можете затем сделать ваши манипуляции.

Чтобы получить последнюю дату месяца, мы делаем что-то вроде этого:

from datetime import date, timedelta import calendar last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1]) 

Теперь, чтобы объяснить, что мы делаем здесь, мы разделим его на две части:

во-первых, получаем количество дней текущего месяца, для которых мы используем диапазон месяцев, о котором Блэр Конрад уже упоминал о своем решении:

calendar.monthrange(date.today().year, date.today().month)[1] 

во-вторых, получение самой последней даты, которую мы делаем с помощью замены, например

>>> date.today() datetime.date(2017, 1, 3) >>> date.today().replace(day=31) datetime.date(2017, 1, 31) 

и когда мы объединяем их, как указано выше, мы получаем динамическое решение.

Хотя этот код может помочь решить проблему, он не объясняет, почему и / или как он отвечает на вопрос. Предоставление этого дополнительного контекста значительно улучшило бы его долгосрочную образовательную ценность. Пожалуйста, измените свой ответ, чтобы добавить объяснение, в том числе, какие ограничения и предположения применяются.

Это кажется самым простым . если вы хотите дать ему две строки, вы можете получить хорошее date.replace(day=day) чтобы все date.replace(day=day) что происходит.

import datetime now = datetime.datetime.now() start_month = datetime.datetime(now.year, now.month, 1) date_on_next_month = start_month + datetime.timedelta(35) start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1) last_day_month = start_next_month - datetime.timedelta(1) 

Самый простой способ (без импорта календаря) — получить первый день следующего месяца, а затем вычесть из него день.

import datetime as dt from dateutil.relativedelta import relativedelta thisDate = dt.datetime(2017, 11, 17) last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1) print last_day_of_the_month 
datetime.datetime(2017, 11, 30, 0, 0) 

PS: Этот код работает быстрее по сравнению с подходом import calendar ; см. ниже:

import datetime as dt import calendar from dateutil.relativedelta import relativedelta someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)] start1 = dt.datetime.now() for thisDate in someDates: lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1) print ('Time Spent= ', dt.datetime.now() - start1) start2 = dt.datetime.now() for thisDate in someDates: lastDay = dt.datetime(thisDate.year, thisDate.month, calendar.monthrange(thisDate.year, thisDate.month)[1]) print ('Time Spent= ', dt.datetime.now() - start2) 
Time Spent= 0:00:00.097814 Time Spent= 0:00:00.109791 

Этот код предполагает, что вы хотите указать дату последнего дня месяца (т.е. не только часть DD, но и всю дату YYYYMMDD)

Источник

Читайте также:  Linux php установить pdo
Оцените статью