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

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


当前回答

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

逻辑很简单。如果明天是下个月的第一天,那么今天就是实际月份的最后一天。下面是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")

其他回答

使用dateutil.rrelatedelta

dt + dateutil.relativedelta.relativedelta(months=1, day=1, days=-1)

months=1,days=1将dt移到下个月的第一个日期,然后days=-1将新日期移到上一个日期,这正好是当前月份的最后一个日期。

下面是一个基于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 lambda查找下个月第一天的元组表示形式,并滚动到下一年。month_end lambda将日期(dte)转换为元组,应用next_month并创建新日期。那么“月底”就是下个月的第一天减去时间增量(天=1)。

from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)

如果您需要获得一个月的第一天的0:00时间,并且不想导入任何特殊的库,您可以这样写

import pytz
from datetime import datetime, timedelta

# get now time with timezone (optional)
now = datetime.now(pytz.UTC)

# get first day on this month, get last day on prev month and after get first day on prev month with min time
fist_day_with_time = datetime.combine((now.replace(day=1) - timedelta(days=1)).replace(day=1), datetime.min.time())

2月28日至29日,12月至1月,以及另一个问题日期,工作正常。

在Python 3.7中,有一个未记录的calendar.monthlen(年,月)函数:

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

它相当于记录的日历。monthrange(年,月)[1]调用。