检查Python中是否为月末

9

我正在编写代码以获取去年的数据。我想要将早期日期四舍五入,如下所示:如果是2015年7月14日,我需要2014年8月1日至2015年7月14日的数据。

df = pd.read_csv('MyData.csv') 
df['recvd_dttm'] = pd.to_datetime(df['recvd_dttm'])
range_max = datetime.datetime.now() 
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)
if datetime.datetime.now() == is_month_end:

# take slice with final week of data
df = df[(df['recvd_dttm'] >= range_min) & 
               (df['recvd_dttm'] <= range_max)]

我的问题是,当日期为2015年7月31日时,我的代码会跳到下个月末,实际上省略了整个月。

我正在尝试使用for循环来解决这个问题。

如果是月底:

range_min = range_max - pd.tseries.offsets.DateOffset(years=1)

否则:

range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)

我该如何让Python检查月末?MonthEnd只是一个偏移函数。


1
你是否查看了 calendar 模块中提供的所有功能?例如,你可以使用它来查找一个月中的最后一天。 - Bryan Oakley
8个回答

17

我们可以使用一个简短的函数,只利用datetime来避免导入calendar模块。

如果明天的月份与今天的月份不同,那么这意味着今天是当前月份的最后一天。我们可以使用一个简短的函数来编写程序来检查这一点:

import datetime 
def end_of_month(dt):
    todays_month = dt.month
    tomorrows_month = (dt + datetime.timedelta(days=1)).month
    return tomorrows_month != todays_month

现在,针对你的特定使用情况:

now = datetime.datetime.now()
if end_of_month(now):
    range_min = range_max - pd.tseries.offsets.DateOffset(years=1)
else: 
    range_min = range_max - pd.tseries.offsets.DateOffset(years=1) +pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)

1
一个小简化:return tomorrows_month != todays_month - nofinator
@nofinator 好的,谢谢! - Chris Greening

8

我会使用日历模块的monthrange方法来查找月份的最后一天:

    def check_if_last_day_of_week(date):
        import datetime
        import calendar
        #  calendar.monthrange return a tuple (weekday of first day of the 
        #  month, number  
        #  of days in month)
        last_day_of_month = calendar.monthrange(date.year, date.month)[1]
        # here i check if date is last day of month
        if date == datetime.date(date.year, date.month, last_day_of_month):
            return True
        return False


>>> date = datetime.date(2018, 12, 31)
>>> check_if_last_day_of_week(date)
True

3
如果第二天是另一个月份,这意味着它是该月的最后一天。
def check_if_last_day_of_month(to_date):
    delta = datetime.timedelta(days=1)
    next_day = to_date + delta
    if to_date.month != next_day.month:
        return True
    return False

2
这个解决方案很好,但请避免使用“if条件返回True否则返回False”的模式。你可以直接写成“return condition”。 - Ilan Segal

1

我正在使用Pandas,不想包含其他库,所以我使用了这个方法来检查是否为月底和年底:

import pandas as pd

my_date = '31-12-2021'

current_data = pd.to_datetime(my_date, format='%d-%m-%Y')
current_month = current_data.month
current_year = current_data.year

following_day = current_data + pd.DateOffset(1)
tomorrows_month = following_day.month
tomorrows_year = following_day.year

is_last_day_of_month = True if tomorrows_month != current_month else False
is_last_day_of_year = True if tomorrows_year != current_year else False

我喜欢这个,因为你使用了 Pandas 库。正是我在寻找的东西。 - Behdad Abdollahi Moghadam
你可以这样做:is_last_day_of_month = (tomorrows_month != current_month) - Behdad Abdollahi Moghadam

1
这是一种纯Python方法,还考虑了二月份的闰年问题:
# total days in every month during non leap years
M_DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def isleap(year):
    """Return True for leap years, False for non-leap years."""
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)


def days_in_month(year, month):
    """Returns total number of days in a month accounting for leap years."""
    return M_DAYS[month] + (month == 2 and isleap(year))


def is_monthend(ref_date):
    """Checks whether a date is also a monthend"""
    return ref_date.day == days_in_month(ref_date.year, ref_date.month)

0
好的,这是我做的。找到了BryanOakley建议的日历模块,并制作了这个循环。它检查当前日期并检查它是否与月底相同,并相应地选择range_min。
if datetime.datetime.now().day == calendar.monthrange(date.year, date.month)[1]:
    range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.DateOffset(days=1)
else:
    range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)

0
import datetime
def find_curr_month_end_date(curr_date):
    if(curr_date.month != 12):
        next_month_first_date= curr_date.replace(day=1).replace(month=curr_date.month+1)
    else:
        next_month_first_date= curr_date.replace(day=1).replace(month=1).replace(year=curr_date.year+1)

    curr_month_end_date = next_month_first_date - datetime.timedelta(days=1)

    return curr_month_end_date


curr_date = datetime.datetime.today() 
# or curr_date = datetime.datetime.strptime("2020-12-16","%Y-%m-%d")
curr_month_end_date = 
find_curr_month_end_date(curr_date)

-2
这是一个简短的函数来实现这个功能。它需要dateutil模块,以便您可以进行相对日期计算。
import datetime
from dateutil.relativedelta import relativedelta

def lastyear_period_start(current_date):
    last_year = current_date - relativedelta(months=11)
    return datetime.date(last_year.year, last_year.month, 1)

它可以这样使用:

dates = [
    datetime.datetime(2010, 2, 27),
    datetime.datetime(2011, 2, 27),
    datetime.datetime(2012, 2, 27),
    datetime.datetime(2013, 2, 27),
    datetime.datetime(2014, 2, 27),
    datetime.datetime(2010, 7, 27),
    datetime.datetime(2011, 7, 27),
    datetime.datetime(2012, 7, 27),
    datetime.datetime(2013, 7, 27),
    datetime.datetime(2014, 7, 27),
    datetime.datetime(2015, 7, 14),
    datetime.datetime(2015, 7, 31),
    datetime.datetime(2011, 2, 28),
    datetime.datetime(2012, 2, 29),
    datetime.datetime(2013, 2, 28),
]

for d in dates:
    print d, lastyear_period_start(d)

这将打印以下内容

2010-02-27 00:00:00 2009-03-01
2011-02-27 00:00:00 2010-03-01
2012-02-27 00:00:00 2011-03-01
2013-02-27 00:00:00 2012-03-01
2014-02-27 00:00:00 2013-03-01
2010-07-27 00:00:00 2009-08-01
2011-07-27 00:00:00 2010-08-01
2012-07-27 00:00:00 2011-08-01
2013-07-27 00:00:00 2012-08-01
2014-07-27 00:00:00 2013-08-01
2015-07-14 00:00:00 2014-08-01
2015-07-31 00:00:00 2014-08-01
2011-02-28 00:00:00 2010-03-01
2012-02-29 00:00:00 2011-03-01
2013-02-28 00:00:00 2012-03-01

在这个函数中,我们执行了两个简单的步骤:
  • last_year = current_date - relativedelta(months=11)
首先,我们根据传递给函数的日期找出了11个月前的日期。
  • return datetime.date(last_year.year, last_year.month, 1)
然后,我们返回该月的第一天。
在上面的输出中,您可以看到这也考虑了闰年。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接