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

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


当前回答

编辑:查看@Blair Conrad的答案以获得更清洁的解决方案


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

其他回答

如果只有今天是一个月的最后一天,而日期并不重要,那么我更喜欢使用下面的条件。

逻辑很简单。如果明天是下个月的第一天,那么今天就是实际月份的最后一天。下面是if-else条件的两个示例。

from datetime import datetime, timedelta

if (datetime.today()+timedelta(days=1)).day == 1:
    print("today is the last day of the month")
else:
    print("today isn't the last day of the month")

如果时区意识很重要。

from datetime import datetime, timedelta
import pytz

set(pytz.all_timezones_set)
tz = pytz.timezone("Europe/Berlin")

dt = datetime.today().astimezone(tz=tz)

if (dt+timedelta(days=1)).day == 1:
    print("today is the last day of the month")
else:
    print("today isn't the last day of the month")

另一个解决方案是这样做:

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)

你可以使用relativeltahttps://dateutil.readthedocs.io/en/stable/relativedelta.htmlmonth_end=<您当月的datetime值>+relativelta(day=31)这将给你最后一天。

这是我只使用标准日期时间库的最简单解决方案:

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)

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

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