4
\$\begingroup\$

This is working. Is it ok?

import calendar
from datetime import datetime


def second_fourth_saturday(year):
    holidays = {}
    for month in range(1, 13):
        cal = calendar.monthcalendar(year, month)
        if cal[0][calendar.SATURDAY]:
            holidays[month] = (
                cal[1][calendar.SATURDAY],
                cal[3][calendar.SATURDAY]
            )
        else:
            holidays[month] = (
                cal[2][calendar.SATURDAY],
                cal[4][calendar.SATURDAY]
            )
    return holidays


if __name__ == "__main__":
    today = datetime.today().day
    tomonth = datetime.today().month
    if today in second_fourth_saturday(2019)[tomonth]:
        print("Enjoy")
    else:
        print("Start Working")
\$\endgroup\$
  • \$\begingroup\$ Do you mean that your program takes the current day and returns whether that current day happens to be the second or fourth Saturday of the current month? \$\endgroup\$ – okcapp Feb 28 at 7:44
  • 2
    \$\begingroup\$ Today is the first Saturday of the current month iff it is Saturday and the day is between 1 and 7, inclusive. It is the second Saturday iff it is Saturday and the day is between 8 and 14, inckusive. It is the third Saturday iff it is Saturday and the day is between 15 and 21, inckusive. It is the fourth Saturday iff it is Saturday and the day is between 22 and 28, inckusive. \$\endgroup\$ – Hagen von Eitzen Feb 28 at 12:19
  • \$\begingroup\$ @okcapp I want to know if today is either second or fourth saturday. In India 2nd and 4th saturdays are government weekly off. 1st 3rd and 5th are working days. \$\endgroup\$ – Rahul Patel Feb 28 at 16:17
  • \$\begingroup\$ @Hagen von Eitzen Really? I am on my mobile. I will test your suggestion when I am on PC. Thanks \$\endgroup\$ – Rahul Patel Feb 28 at 16:21
  • \$\begingroup\$ I suggest you add a little more text to your post. What do you mean, is it okay? \$\endgroup\$ – IEatBagels Mar 1 at 14:47
6
\$\begingroup\$

A few suggestions

  • collections.defaultdict

    holidays = {}
    for month in range(1, 13):
        holidays[month] = []
        ...
    

    There is a module for dictionaries starting with a basic datatype

    from collections import defaultdict
    holidays = defaultdict(tuple)
    

    Secondly you first init it as a list, and afterwards you make it a tuple this is odd. Pick one and stick with it

  • You don't have to calculate all the months only the specific month

    Since you already know which month it is now, just calculate only the month you are interested in

    To do this you would have to give the month as a second parameter

    def second_fourth_saturday(year, month):
        cal = calendar.monthcalendar(year, month)
        ...
    
  • Don't Repeat Yourself

    if cal[0][calendar.SATURDAY]:
        holidays[month] = (
            cal[1][calendar.SATURDAY],
            cal[3][calendar.SATURDAY]
        )
    else:
        holidays[month] = (
            cal[2][calendar.SATURDAY],
            cal[4][calendar.SATURDAY]
        )
    

    If you calculate the weeks beforehand you don't have to repeat yourself

    second_fourth_saturday = (1, 3) if cal[0][calendar.SATURDAY] else (2, 4)
    
  • Return what is asked

    Instead of return a dict of month with second/fourth saturdays, I think it would be more clear if the function returns a boolean value if the day is a second or fourth saturday

Code

from calendar import monthcalendar, SATURDAY
from datetime import datetime

def second_fourth_saturday(date):
    month_calender = monthcalendar(date.year, date.month)
    second_fourth_saturday = (1, 3) if month_calender[0][SATURDAY] else (2, 4)
    return any(date.day == month_calender[i][SATURDAY] for i in second_fourth_saturday)

if __name__ == "__main__":
    is_second_fourth_saturday = second_fourth_saturday(datetime.today())
    print("Enjoy" if is_second_fourth_saturday else "Start working")
\$\endgroup\$
3
\$\begingroup\$

As suggested by @HagenvonEitzen in the comments:

Today is the first Saturday of the current month iff it is Saturday and the day is between 1 and 7, inclusive. It is the second Saturday iff it is Saturday and the day is between 8 and 14, inc[l]usive. It is the third Saturday iff it is Saturday and the day is between 15 and 21, inc[l]usive. It is the fourth Saturday iff it is Saturday and the day is between 22 and 28, inc[l]usive.

So, just test against that:

from calendar import SATURDAY

def second_fourth_saturday(date):
    if date.weekday() != SATURDAY:
        return False
    day = date.day
    return day in range(8, 14 + 1) or day in range(22, 28 + 1)

This uses the fact that in tests for range are constant time in Python 3 (in Python 2 they were not).

You could also hardcode those numbers:

POSSIBLE_DAYS = set(range(8, 14 + 1)) | set(range(22, 28 + 1))

def second_fourth_saturday(date):
    return date.weekday() == SATURDAY and date.day in POSSIBLE_DAYS
\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks. This is a good strategy. I could not initially understood @HagenvonEitzen 's comment \$\endgroup\$ – Rahul Patel Mar 5 at 10:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.