Вопрос:

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

python date

257861 просмотра

30 ответа

23583 Репутация автора

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

Если стандартная библиотека не поддерживает это, поддерживает ли пакет dateutil это?

Автор: Cristian Источник Размещён: 04.09.2008 12:54

Ответы (30)


64 плюса

161104 Репутация автора

РЕДАКТИРОВАТЬ: См. Ответ @Blair Conrad для более чистого решения


>>> import datetime
>>> datetime.date (2000, 2, 1) - datetime.timedelta (days = 1)
datetime.date(2000, 1, 31)
>>> 
Автор: John Millikin Размещён: 04.09.2008 01:26

40 плюса

161741 Репутация автора

РЕДАКТИРОВАТЬ: см. Мой другой ответ . Он имеет лучшую реализацию, чем эта, которую я оставлю здесь на всякий случай, если кому-то интересно посмотреть, как можно «свернуть свой собственный» калькулятор.

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

Следующее не особенно элегантно, но чтобы выяснить последний день месяца, в котором живет любая конкретная дата, вы можете попробовать:

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)
Автор: Blair Conrad Размещён: 04.09.2008 02:25

921 плюса

161741 Репутация автора

Решение

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

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

>>> 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)

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

Автор: Blair Conrad Размещён: 04.09.2008 12:44

12 плюса

0 Репутация автора

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

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)
Автор: Craig Размещён: 10.12.2008 03:47

-8 плюса

122 Репутация автора

у меня есть простое решение:

import datetime   
datetime.date(2012,2, 1).replace(day=1,month=datetime.date(2012,2,1).month+1)-timedelta(days=1)
datetime.date(2012, 2, 29)
Автор: francois Размещён: 21.08.2012 11:09

1 плюс

41512 Репутация автора

Это не решает основной вопрос, но есть один хороший трюк, чтобы получить последний день недели в месяце - использовать calendar.monthcalendarматрицу дат, организованную с понедельника в качестве первого столбца до воскресенья в качестве последнего.

# Some random date.
some_date = datetime.date(2012, 5, 23)

# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()

print last_weekday
31

Все [0:-2]дело в том, чтобы сбрить колонки выходных и выбросить их. Даты, которые выходят за пределы месяца, обозначены 0, поэтому максимум фактически игнорирует их.

Использование numpy.ravelне является строго необходимым, но я ненавижу полагаться на простое соглашение , numpy.ndarray.maxкоторое сгладит массив, если не будет указано, по какой оси рассчитывать.

Автор: ely Размещён: 14.11.2012 08:06

118 плюса

4770 Репутация автора

Если вы не хотите импортировать 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
Автор: Augusto Men Размещён: 26.11.2012 12:48

37 плюса

2449 Репутация автора

На самом деле это довольно просто 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)
Автор: Vince Spicer Размещён: 21.02.2013 04:09

5 плюса

391 Репутация автора

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)
Автор: Анатолий Панин Размещён: 16.06.2013 04:51

1 плюс

637 Репутация автора

Если вы хотите создать свою маленькую функцию, это хорошая отправная точка:

def eomday(year, month):
    """returns the number of days in a given month"""
    days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    d = days_per_month[month - 1]
    if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
        d = 29
    return d

Для этого вы должны знать правила для високосных лет:

  • каждый четвертый год
  • за исключением каждых 100 лет
  • но снова каждые 400 лет
Автор: mathause Размещён: 30.04.2014 08:33

10 плюса

9644 Репутация автора

from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
Автор: Collin Anderson Размещён: 03.05.2014 05:16

3 плюса

149 Репутация автора

Для меня это самый простой способ:

selected_date = date(some_year, some_month, some_day)

if selected_date.month == 12: # December
     last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
     last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
Автор: KravAn Размещён: 24.07.2014 09:16

17 плюса

302 Репутация автора

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

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

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

Автор: Satish Reddy Размещён: 27.12.2014 12:54

8 плюса

715 Репутация автора

>>> 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
Автор: Vatsal Размещён: 05.03.2015 08:02

1 плюс

390 Репутация автора

Используйте панд!

def isMonthEnd(date):
    return date + pd.offsets.MonthEnd(0) == date

isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
Автор: Steve Schulist Размещён: 24.07.2015 07:59

0 плюса

6 Репутация автора

import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]

Выход:

31



Будет напечатан последний день текущего месяца. В этом примере это было 15 мая 2016 года. Таким образом, ваш вывод может быть другим, однако выходной будет столько же дней, сколько текущий месяц. Отлично, если вы хотите проверить последний день месяца, запустив ежедневную работу cron.

Так:

import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today

Выход:

False

Если это не последний день месяца.

Автор: Audstanley Размещён: 16.05.2016 04:22

1 плюс

1266 Репутация автора

Я предпочитаю этот путь

import datetime
import calendar

date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)
Автор: MikA Размещён: 25.08.2016 09:48

7 плюса

71 Репутация автора

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

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)

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

Автор: Siddharth K Размещён: 30.08.2016 09:14

2 плюса

365 Репутация автора

Вы можете рассчитать дату окончания самостоятельно. простая логика - вычесть день из даты начала следующего месяца. :)

Так что напишите собственный метод,

import datetime

def end_date_of_a_month(date):


    start_date_of_this_month = date.replace(day=1)

    month = start_date_of_this_month.month
    year = start_date_of_this_month.year
    if month == 12:
        month = 1
        year += 1
    else:
        month += 1
    next_month_start_date = start_date_of_this_month.replace(month=month, year=year)

    this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
    return this_month_end_date

Вызов,

end_date_of_a_month(datetime.datetime.now().date())

Он вернет дату окончания этого месяца. Передайте любую дату этой функции. возвращает вам дату окончания этого месяца.

Автор: Vipul Vishnu av Размещён: 02.09.2016 08:47

8 плюса

548 Репутация автора

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

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

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

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

Автор: Blake Размещён: 27.11.2016 10:01

-3 плюса

1 Репутация автора

Надеюсь, это очень полезно. Попробуйте на этом пути .. нам нужно импортировать пакет

import time
from datetime import datetime, date
from datetime import timedelta
from dateutil import relativedelta

  start_date = fields.Date(
        string='Start Date', 
        required=True,
        ) 

    end_date = fields.Date(
        string='End Date', 
        required=True,
        )

    _defaults = {
        'start_date': lambda *a: time.strftime('%Y-%m-01'),
        'end_date': lambda *a: str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10],
    }
Автор: Vinoth Jo Размещён: 27.09.2017 12:23

3 плюса

151 Репутация автора

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

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, но и всю дату ГГГГММДД)

Автор: Vishal Размещён: 17.11.2017 07:38

0 плюса

21 Репутация автора

Если вы передаете диапазон дат, вы можете использовать это:

def last_day_of_month(any_days):
    res = []
    for any_day in any_days:
        nday = any_day.days_in_month -any_day.day
        res.append(any_day + timedelta(days=nday))
    return res
Автор: JLord Размещён: 12.03.2018 03:14

-1 плюса

7 Репутация автора

Вот решение на основе Python Lambdas:

next_month = lambda y, m, d: (y, m + 1, 1) if m + 1 < 13 else ( y+1 , 1, 1)
month_end  = lambda dte: date( *next_month( *dte.timetuple()[:3] ) ) - timedelta(days=1)

next_monthЛямбда находит кортеж представление в первый день следующего месяца, и переворачивается на следующий год. month_endЛямбда преобразует дату ( dte) к кортежу, применяется next_monthи создает новую дату. Тогда «конец месяца» - это минус первый день следующего месяца timedelta(days=1).

Автор: Johannes Blaschke Размещён: 07.04.2018 10:52

0 плюса

503 Репутация автора

В приведенном ниже коде get_last_day_of_month (dt) даст вам это с датой в строковом формате, например, «YYYY-MM-DD».

import datetime

def DateTime( d ):
    return datetime.datetime.strptime( d, '%Y-%m-%d').date()

def RelativeDate( start, num_days ):
    d = DateTime( start )
    return str( d + datetime.timedelta( days = num_days ) )

def get_first_day_of_month( dt ):
    return dt[:-2] + '01'

def get_last_day_of_month( dt ):
    fd = get_first_day_of_month( dt )
    fd_next_month = get_first_day_of_month( RelativeDate( fd, 31 ) )
    return RelativeDate( fd_next_month, -1 )
Автор: Pulkit Bansal Размещён: 14.11.2018 05:12

2 плюса

1509 Репутация автора

Вот еще один ответ. Никаких дополнительных пакетов не требуется.

datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)

Получите первый день следующего месяца и вычтите из него один день.

Автор: Kevan Swanberg Размещён: 29.11.2018 10:29

1 плюс

2632 Репутация автора

Вы можете использовать родственник Аддета https://dateutil.readthedocs.io/en/stable/relativedelta.html month_end = <your datetime value within the month> + relativedelta(day=31) , который даст вам последний день.

Автор: Jake Boomgaarden Размещён: 11.12.2018 01:41

3 плюса

278966 Репутация автора

В Python 3.7 есть недокументированная calendar.monthlen(year, month)функция :

>>> calendar.monthlen(2002, 1)
31
>>> calendar.monthlen(2008, 2)
29
>>> calendar.monthlen(2100, 2)
28

Это эквивалентно документированному calendar.monthrange(year, month)[1]звонку .

Автор: jfs Размещён: 16.02.2019 03:09

0 плюса

1100 Репутация автора

Это самое простое решение для меня, использующее только стандартную библиотеку datetime:

import datetime

def get_month_end(dt):
    first_of_month = datetime.datetime(dt.year, dt.month, 1)
    next_month_date = first_of_month + datetime.timedelta(days=32)
    new_dt = datetime.datetime(next_month_date.year, next_month_date.month, 1)
    return new_dt - datetime.timedelta(days=1)
Автор: Toby Petty Размещён: 21.06.2019 03:49

0 плюса

88995 Репутация автора

Чтобы получить последний день месяца просто с datetimeпомощью этой простой функции:

import datetime

def last_day_of_month(date: datetime.date) -> datetime.date:
    return date.replace(month=date.month % 12 + 1, day=1) - datetime.timedelta(days=1)

Вы также можете использовать, calendar.monthrange()чтобы узнать количество дней в месяце и соответствующим образом обновить дату, хотя в моих тестах это оказалось медленнее, чем в предыдущей версии:

import calendar, datetime

def last_day_of_month(date: datetime.date) -> datetime.date:
    return date.replace(day=calendar.monthrange(date.year, date.month)[1])
Автор: Eugene Yarmash Размещён: 24.06.2019 02:08
Вопросы из категории :
32x32