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

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


当前回答

import datetime

now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)

其他回答

更简单地说:

import datetime
now = datetime.datetime.now()
datetime.date(now.year, 1 if now.month==12 else now.month+1, 1) - datetime.timedelta(days=1)

这个对我很有用:

df['daysinmonths'] = df['your_date_col'].apply(lambda t: pd.Period(t, freq='S').days_in_month)

参考来源:https://stackoverflow.com/a/66403016/16607636

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

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

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))

下面是一个基于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)。

最简单的方法是使用日期时间和一些日期数学,例如从下个月的第一天减去一天:

import datetime

def last_day_of_month(d: datetime.date) -> datetime.date:
    return (
        datetime.date(d.year + d.month//12, d.month % 12 + 1, 1) -
        datetime.timedelta(days=1)
    )

或者,您可以使用calendar.monthrange()获取一个月的天数(考虑闰年)并相应地更新日期:

import calendar, datetime

def last_day_of_month(d: datetime.date) -> datetime.date:
    return d.replace(day=calendar.monthrange(d.year, d.month)[1])

快速的基准测试表明,第一个版本明显更快:

In [14]: today = datetime.date.today()

In [15]: %timeit last_day_of_month_dt(today)
918 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [16]: %timeit last_day_of_month_calendar(today)
1.4 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)