9

I am trying to write a Python script that will calculate how many business days are in the current month. For instance if month = August then businessDays = 22.

Here is my code for discovering the month:

def numToMonth( num ):
   months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
   return str(months[ num - 1 ])

This code works fine, and I could hard code another function to match the month with how many days that month should contain...but this does not help me with business days.

Any help? I'm used to C, C++ so please don't bash my Python "skills".

Edit: I cannot install any extra libraries or modules on my machine, so please post answers using default Python modules. (Python 2.7, datetime etc.) Also, my PC has Windows 7 OS.

Jacob Bridges
  • 725
  • 2
  • 8
  • 16

8 Answers8

15

This is a long-winded way, but at least it works and doesn't require anything other than the standard modules.

import datetime

now = datetime.datetime.now()
holidays = {datetime.date(now.year, 8, 14)} # you can add more here
businessdays = 0
for i in range(1, 32):
    try:
        thisdate = datetime.date(now.year, now.month, i)
    except(ValueError):
        break
    if thisdate.weekday() < 5 and thisdate not in holidays: # Monday == 0, Sunday == 6 
        businessdays += 1

print businessdays
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
chthonicdaemon
  • 19,180
  • 2
  • 52
  • 66
  • Thanks for your help! I had to modify the code a little.. (Your indentation was strange) But it works. Thanks again. – Jacob Bridges Aug 14 '13 at 15:44
  • No problem. In what way was my indentation strange? The code above only catches PEP8 errors for the long line and the comment style. – chthonicdaemon Aug 15 '13 at 06:21
  • looks like a hack but I would have done like that :) and it works. So thanks. Small remark: why hardcoding the year? to get a budget to ask your bosses to reopen the program in 2014 for heavy maintenance ? :) – Jean-François Fabre Nov 27 '17 at 12:30
  • @Jean-FrançoisFabre In my country (South Africa) most holidays are not on exactly specified dates every year because the date they are observed changes to the following Monday if they fall on a weekend. So I would actually imagine you will have a yearly calendar for holidays which will be different every year. ;-) – chthonicdaemon Nov 27 '17 at 17:47
9

I would simply use built-in module calendar:

import calendar

weekday_count = 0
cal = calendar.Calendar()

for week in cal.monthdayscalendar(2013, 8):
    for i, day in enumerate(week):
        # not this month's day or a weekend
        if day == 0 or i >= 5:
            continue
        # or some other control if desired...
        weekday_count += 1

print weekday_count

that's it.

kirpit
  • 4,419
  • 1
  • 30
  • 32
7

I would like to add my answer.

I'm using Calendar, list comprehension, and length to count how many days is the working day a particular month.

Here is my code:

#!/bin/env python

import calendar
import datetime

now = datetime.datetime.now()

cal = calendar.Calendar()

working_days = len([x for x in cal.itermonthdays2(now.year, now.month) if x[0] !=0 and x[1] < 5])

print "Total working days this month: " + str(working_days)
Sharuzzaman Ahmat Raslan
  • 1,557
  • 2
  • 22
  • 34
1

I stole this from Sharuzzaman's solution and added a dict for holidays and turned it into a function:

import calendar
cal = calendar.Calendar()

def get_wdim(year,month):
    working_days = len([x for x in cal.itermonthdays2(year, month) if x[0] !=0 and x[1] < 5]) 
    holidays = {
        1:1,
        2:1,
        4:1,
        5:1,
        7:1,
        9:1,
        10:1,
        11:4,
        12:1
    }
    return int(working_days) - holidays.get(month,0)


wdim2022 = [get_wdim(2022,x) for x in list(range(1,13)) ]   

0

UPDATE: OP can't use any external libraries. Then you will have to build some tables based on determining the day of the week from the calendar.

The formula is d + m + y + y/4 + (c mod 7), where: d is the day of the month, m is the month's number in the months table, y is the last two digits of the year, and c is the century number.

It's tedious but not impossible!

ORIG answer: It's quite tedious to code yourself, because August 01, 2013 and August 01, 2012 are not necessarily the same day of the week. I'd start with the 'date' class in python (details here

from datetime import date
datetime.date(2002, 3, 11)
t = d.timetuple()
for i in t:     
   print i

In particular, check out the 'datetime.weekday()' function.

philshem
  • 24,761
  • 8
  • 61
  • 127
0

This is relatively simple, just break it down into steps:

  1. You need to be able to loop through the days in a month.
  2. You need to be able to determine the day of a week that any given date falls on. Wikipedia lists some methods.
  3. Then you need only flag days of the week as business days or not.

Combine these steps and you'll have a working method.

Jack Aidley
  • 19,439
  • 7
  • 43
  • 70
  • Thanks for encouraging me to do more research, but I was looking for a method already built in to Python. If it doesn't exist, I will post whatever algorithm I create as an answer. – Jacob Bridges Aug 14 '13 at 14:13
0

You could take a look at datetime.datetime.dayofweek() but if you are not allowed to use an external library then you need to:

  1. pick a date that you know the day of week of - best if it is a Monday
  2. come up with a formulae for the number of days since then that the first of a given month is.
  3. for each of the days in the month the (number of days since your day) % 7 in [5, 6] is a weekend.
Steve Barnes
  • 27,618
  • 6
  • 63
  • 73
0

Acknowledging the OP stated external libraries could not be used, given the ranking of the question in searches (together with the fact this wasnt stated in the title), I figured I'd share a pandas solution which provides a solution spanning multiple months, with results presented in a df.

    import pandas as pd
    business_days = pd.date_range(start, end, freq='B')
    pd.DataFrame(index=business_days, data=[1] * len(business_days)).resample('M').sum()
kowpow
  • 95
  • 2
  • 8