有没有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天?

如果标准库不支持,dateutil包是否支持此功能?


当前回答

编辑:看看我的另一个答案。它有一个比这个更好的实现,我把它放在这里,以防有人有兴趣看到如何“运行自己的”计算器。

@约翰·米利金给出了一个很好的答案,但计算下个月的第一天又增加了复杂性。

以下内容不是特别优雅,但要计算出任何给定日期所在月份的最后一天,您可以尝试:

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)

其他回答

如果不想导入日历模块,还可以使用简单的两步功能:

import datetime

def last_day_of_month(any_day):
    # The day 28 exists in every month. 4 days later, it's always next month
    next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
    # subtracting the number of the current day brings us back one month
    return next_month - datetime.timedelta(days=next_month.day)

输出:

>>> for month in range(1, 13):
...     print(last_day_of_month(datetime.date(2022, month, 1)))
...
2022-01-31
2022-02-28
2022-03-31
2022-04-30
2022-05-31
2022-06-30
2022-07-31
2022-08-31
2022-09-30
2022-10-31
2022-11-30
2022-12-31

如果传入日期范围,则可以使用以下命令:

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

使用熊猫!

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

我认为这比其他一些答案更具可读性:

from datetime import timedelta as td
from datetime import datetime as dt
today = dt.now()
a_day_next_month = dt(today.year, today.month, 27) + td(days=5)
first_day_next_month =  dt(a_day_next_month.year, a_day_next_month.month, 1)
last_day_this_month = first_day_next_month - td(days=1)

使用datetime月包。

$ pip install datetime-month
$ python
>>> from month import XMonth
>>> Xmonth(2022, 11).last_date()
datetime.date(2022, 11, 30)