Получить последний день месяца в Python - PullRequest
514 голосов
/ 04 сентября 2008

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

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

Ответы [ 28 ]

910 голосов
/ 04 сентября 2008

Я не заметил этого раньше, когда просматривал документацию для модуля календаря , но метод с именем 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)

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

115 голосов
/ 26 ноября 2012

Если вы не хотите импортировать модуль 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
62 голосов
/ 04 сентября 2008

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


>>> import datetime
>>> datetime.date (2000, 2, 1) - datetime.timedelta (days = 1)
datetime.date(2000, 1, 31)
>>> 
40 голосов
/ 04 сентября 2008

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

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

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

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)
36 голосов
/ 21 февраля 2013

Это на самом деле довольно просто с 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)
16 голосов
/ 27 декабря 2014

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

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

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

13 голосов
/ 10 декабря 2008

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

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)
10 голосов
/ 03 мая 2014
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
8 голосов
/ 27 ноября 2016

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

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

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

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

8 голосов
/ 05 марта 2015
>>> 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...