0

If I have a month (2017,5), and I would like to get the 10th weekday of that month -- is there a quick way to do it? Brute force, I know I could loop through every calendar day of time and create a massive mapping. But wondering if there is an easier way.

Sorry if this has been asked before! Can't seem to find a solution in python.

oz123
  • 27,559
  • 27
  • 125
  • 187
user487588
  • 722
  • 2
  • 9
  • 18
  • Sorry but what is a weekday? Not clear what you want, 10th of may, or do you want the day of the week name, e.g. monday? – RvdK May 19 '16 at 09:17
  • Ah, should have been more clear. So, I don't want the 10th of may. But instead I want the function to return a datetime which is the 10th day in may excluding weekends. – user487588 May 19 '16 at 09:39

2 Answers2

2

Given a datetime.date object you can use the .isoweekday method to check the day of the week, all weekdays return values <=5 so:

def is_business_day(day):
    return day.isoweekday() < 5

You can use it like this to find all weekdays in a given month

In [29]: filter(lambda x: x[0] if x[1] else None, 
                [(d, is_business_day(datetime.date(2017,5,d))) 
                 for d in range(1,31)])
Out[29]: 
[(1, True),
 (2, True),
 (3, True),
 (4, True),
 (8, True),
 (9, True),
 (10, True),
 (11, True),
 (15, True),
 (16, True),
 (17, True),
 (18, True),
 (22, True),
 (23, True),
 (24, True),
 (25, True),
 (29, True),
 (30, True)]

This code isn't safe though. It does not check the boundaries of a month.

In [34]: filter(lambda x: x[1] if x[1] else None, 
                [(d, is_business_day(datetime.date(2017,2,d))) 
                  for d in range(1,31)])
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-34-486d782346bd> in <module>()
----> 1 filter(lambda x: x[1] if x[1] else None, [(d, is_business_day(datetime.date(2017,2,d))) for d in range(1,31)])

ValueError: day is out of range for month

So you will have to make some more logic to figure the boundaries of months.

To figure out the boundaries of each month see How to find number of days in the current month

You can also improve the outputted formatted a bit:

In [43]: [d for d in range(1,31) if is_business_day(datetime.date(2017,5,d))]
Out[43]: [1, 2, 3, 4, 8, 9, 10, 11, 15, 16, 17, 18, 22, 23, 24, 25, 29, 30]

update, now the last comment of the OP is published, get the Xth business day:

Building on the latest list comperhansion, if x is the 9 business day:

In [6]: [d for d in range(1,31) if 
         is_business_day(datetime.date(2017,5,d))][9-1]
Out[6]: 15

In [7]: x=9

In [8]: [d for d in range(1,31) if 
         is_business_day(datetime.date(2017,5,d))][x-1]
Out[8]: 15
Community
  • 1
  • 1
oz123
  • 27,559
  • 27
  • 125
  • 187
0

You want to implement a basic algorithm to solve it, there's quite a few but there's a very simple method listed on this wikipedia article: https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week

Nicholas Smith
  • 11,642
  • 6
  • 37
  • 55