tkyass
tkyass

Reputation: 3186

finding last business day of a month in python

I'm trying to find last business day of of the month. I wrote the code below for that and it works fine but I was wondering if there is a cleaner way of doing it?

from  datetime import date,timedelta
import datetime
import calendar

today=datetime.date.today()

last = today.replace(day=calendar.monthrange(today.year,today.month)[1])

if last.weekday()<5:
    print last

else:
    print last-timedelta(days=1+last.weekday()-5)

Thanks in advance!

Upvotes: 19

Views: 50077

Answers (9)

UCCH
UCCH

Reputation: 1

Here another bit generalized function

def is_last_day_in_period(date, freq='bm'):
""" Checks if particular date is last date of a specific period

e.g. 'm', 'bm', 'q', 'bq', 'a', 'ba'

Parameters
----------
date : datelike
    date to evaluate
freq : str
    valid pandas frequency string

Returns
-------
check : bool
    if last day in period
"""

date = pd.Timestamp(date)
int_dates = pd.date_range(start=date, end=date + Day(1000), freq=freq)
check = int_dates[int_dates >= date][0] == date

return check

Upvotes: 0

gregV
gregV

Reputation: 1097

slight upgrade over @Elke's answer when today is in fact a month end, to ensure it would not get rolled:

run_date = pd.Timestamp('2023-07-31')

run_date.replace(day=1) + pd.offsets.BMonthEnd()
Out[27]: Timestamp('2023-07-31 00:00:00')

run_date.replace(day=1) - pd.offsets.BMonthEnd()
Out[28]: Timestamp('2023-06-30 00:00:00')

Upvotes: 0

VBobCat
VBobCat

Reputation: 2712

For one-liner fans:

import calendar

def last_business_day_in_month(year: int, month: int) -> int:
    return max(calendar.monthcalendar(year, month)[-1][:5])

Upvotes: 10

nhboe
nhboe

Reputation: 11

I needed something intuitively readable and opted for the following:

from datetime import datetime, timedelta
import pandas as pd

def isMonthLastBusinessDay(date):
    lastDayOfMonth = date + pd.offsets.MonthEnd(0)
    isFriday = date.weekday() == 4
    if (date.weekday() < 5 and lastDayOfMonth == date) or (isFriday and lastDayOfMonth == date+timedelta(days=1)) or (isFriday and lastDayOfMonth == date+timedelta(days=2)):
        return True
    else:
        return False

Upvotes: 0

zephyr707
zephyr707

Reputation: 173

with rollforward(d) you will skip to the next month if the date is past the last business day of the current month, so below might be safer for any day of the month:

from datetime import date
import pandas as pd

d = date(2011, 12, 31) # a caturday
pd.bdate_range(end=pd.offsets.MonthEnd().rollforward(d), periods=1)
pd.offsets.BMonthEnd().rollforward(d)

Upvotes: 0

d84_n1nj4
d84_n1nj4

Reputation: 1852

I use this for the first business day of the month but it can be used for last business day of the month as well:

import time
import datetime
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
from dateutil.relativedelta import relativedelta

#Create dates needed to be entered as parameters
today = datetime.date.today()
first = today.replace(day=1)
#End of the Prior Month
eopm = first - datetime.timedelta(days=1)
eopm = eopm.strftime("%Y%m%d")
#Create first business day of current month date
us_bd = CustomBusinessDay(calendar=USFederalHolidayCalendar())
focm = first
nxtMo = today + relativedelta(months=+1)
fonm = nxtMo.replace(day=1)
eocm = fonm - datetime.timedelta(days=1)
first_bd = pd.DatetimeIndex(start = focm, end = eocm, freq= us_bd)
first_bd = first_bd.strftime("%Y%m%d")
#First Business Day of the Month
first_bd = first_bd[0]
#Last Business Day of the Month
lst_day = len(first_bd)-1
last_bd = first_bd[lst_day]

I left some code in there that is not needed for the last business day of the current month, but may be useful to someone.

Upvotes: 2

nyan314sn
nyan314sn

Reputation: 1936

Let's say you want to get the last business days of the month up-to the end of the next two years, the following will work.

   import pandas as pd
   import datetime

   start = datetime.date.today()
   end = datetime.date(start.year+2, 12, 31)
   bussiness_days_rng =pd.date_range(start, end, freq='BM')

Upvotes: 8

Elke
Elke

Reputation: 511

I use the following:

from pandas.tseries.offsets import BMonthEnd
from datetime import date

d=date.today()

offset = BMonthEnd()

#Last day of current month
offset.rollforward(d)

#Last day of previous month
offset.rollback(d)

Upvotes: 35

Tanu
Tanu

Reputation: 1563

You can use Pandas to get business days. Refer http://pandas.pydata.org/pandas-docs/stable/timeseries.html

Also you can refer this https://pypi.python.org/pypi/business_calendar/ for simple business days calculation.

Upvotes: 0

Related Questions