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

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


当前回答

另一种选择是使用递归函数。

第二天是在不同的月份吗?如果是,则当前日期是该月的最后一天。如果第二天在同一个月,请使用第二天重试。

from datetime import timedelta

def last_day_of_month(date):
    if date.month != (date + timedelta(days=1)).month:
        return date
    else:
        return last_day_of_month(date + timedelta(days=1))

其他回答

这并不能解决主要问题,但一个获取一个月内最后一个工作日的好方法是使用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如果不知道要在哪个轴上计算,就会使数组变平的约定。

考虑到不同月份的天数不相等,以下是适用于每个月的标准解决方案。

import datetime
ref_date = datetime.today() # or what ever specified date

end_date_of_month = datetime.strptime(datetime.strftime(ref_date + relativedelta(months=1), '%Y-%m-01'),'%Y-%m-%d') + relativedelta(days=-1)

在上面的代码中,我们只是将一个月添加到所选日期,然后导航到该月的第一天,然后从该日期中减去一天。

另一种选择是使用递归函数。

第二天是在不同的月份吗?如果是,则当前日期是该月的最后一天。如果第二天在同一个月,请使用第二天重试。

from datetime import timedelta

def last_day_of_month(date):
    if date.month != (date + timedelta(days=1)).month:
        return date
    else:
        return last_day_of_month(date + timedelta(days=1))

对我来说,这是最简单的方法:

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)

我在这里找到了有趣的解决方案。提供这些相对的elta参数,可以得到一个月的最后一天:day=31,days=+1,seconds=-1(这是前一天的最后一秒):

import datetime
from dateutil.relativedelta import relativedelta

day_of_febuary = datetime.datetime(2022, 2, 21)
last_day_of_febuary = day_of_febuary + relativedelta(day=31, days=+1, seconds=-1)
print(last_day_of_febuary)
# Output: 2022-02-28 23:59:59