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

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


当前回答

使用dateutil.rrelatedelta

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

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

其他回答

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

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)

如果您不介意使用Pandas,那么使用Timestamp.days_in_month可能是最简单的:

import pandas as pd

> pd.Timestamp(year=2020, month=2, day=1).days_in_month

29

使用datetime月包。

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

这是一个很长(容易理解)的版本,但考虑了闰年。

def last_day_month(year, month):
    leap_year_flag = 0
    end_dates = {
        1: 31,
        2: 28,
        3: 31,
        4: 30,
        5: 31,
        6: 30,
        7: 31,
        8: 31,
        9: 30,
        10: 31,
        11: 30,
        12: 31
    }

    # Checking for regular leap year    
    if year % 4 == 0:
        leap_year_flag = 1
    else:
        leap_year_flag = 0

    # Checking for century leap year    
    if year % 100 == 0:
        if year % 400 == 0:
            leap_year_flag = 1
        else:
            leap_year_flag = 0
    else:
        pass

    # return end date of the year-month
    if leap_year_flag == 1 and month == 2:
        return 29
    elif leap_year_flag == 1 and month != 2:
        return end_dates[month]
    else:
        return end_dates[month]

如果你想制作自己的小功能,这是一个很好的起点:

def eomday(year, month):
    """returns the number of days in a given month"""
    days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    d = days_per_month[month - 1]
    if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
        d = 29
    return d

为此,您必须了解闰年的规则:

每四年除了每100年但每400年一次