Your code looks quite good. You mostly stick to PEP8 though you might want to implement a distance of two empty lines in-between functions on module-level.
Regarding code optimization you may want to make month_days
and day_names
tuples since they do not change and thus may be implemented as invariant constants. While doing this you can also capitalize their names to indicate that they are global constants as you did with the other module-level variables:
MONTH_DAYS = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)DAY_NAMES = ("Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday")
Furthermore, you can make is_leap_year
a one-liner, since the if-else blocks and zero-comparisons are a bit verbose for my taste of "pythonicness":
def is_leap_year(year): return not year % 4 and (year % 100 or not year % 400)
Also I find it a bit intricately, that you pass a tuple date
to find_day
and then access its members via indexes.I suggest changing that to:
def find_day(month, day, year): total = calc_month(month, year) + calc_day(day) + calc_year(year) if total < 0: return day_names[total % -7] else: return day_names[total % 7]def main(): date = input("Enter a day like so <MM, DD, YYYY>: ").split() month = int(date[0]) day = int(date[1]) year = int(date[2]) if month > 12 or month <= 0: print("Invalid month") elif day > month_days[month - 1] or day <= 0: if not (day == 29 and month == 2): print("Invalid day") else: print(find_day(month, day, year))
However, if you really want to handle date
as such a tuple for later re-use, I recommend that you use tuple unpacking in find_day
instead of index accessing for better readability:
def find_day(date): month, day, year = date total = calc_month(month, year) + calc_day(day) + calc_year(year) if total < 0: return day_names[total % -7] else: return day_names[total % 7]