Docstrings / Type hints
These allow you to describe how your code works in a pythonic manner. Docstrings allow IDE's and other documentation tools to see what your function/class does. Type hints allow you to show what types of parameters are accepted, and what types of values are returned.
check_date
Instead of calculating a leap year yourself, you can use calendar.isleap from the [calendar][1] module.
Return comparisons, not raw booleans
Instead of
if day <= day_bound:
return True
return False
do this
return day <= day_bound
Does the exact same thing, but looks a lot nicer.
Split code into functions
You've done a good job splitting your code into functions, but I think you could use one more. Instead of parsing the date in the "main" code, put that code in another function, and pass it the date string.
def get_date_values(...) -> ...:
...
With all these changes, your final code would look something like this:
import re
import calendar
from typing import Tuple, Union
def check_date(day: int, month: int, year: int) -> bool:
"""
Returns a bool based on if the date passed is a valid date.
:param int day: Day.
:param int month: Month.
:param int year: Year.
:return: True if a valid date, False otherwise.
"""
# April, June, September, November = 30 days/ February = 28 days, unless leapyear so 29/ rest has 31 days
month_dict = {4: 30, 6: 30, 9: 30, 11: 30, 2: 28}
day_bound = month_dict.get(month, 31)
if day_bound == 28:
if calendar.isleap(year):
day_bound = 29
return day <= day_bound
def get_date_values(date: str) -> Union[Tuple[int, int, int], None]:
"""
Returns a tuple containing the day, month, and year of the passed date.
:param str date: Date to parse and retrieve values.
:return: Either a Tuple, or for an invalid date, None.
"""
date_regex = re.compile(r"([0-2]\d|3[01])/(0\d|1[0-2])/([12]\d{3})")
match = date_regex.search(date)
if match:
return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
return None
if __name__ == "__main__":
date = "31/02/2020" #DD/MM/YYYY
if check_date(*get_date_values(date)):
print('Valid Date!')
else:
print('Invalid Date!')
I'll explain a bit more since I made some changes I haven't mentioned already.
Unpacking
if check_date(*get_date_values(date)):
This line unpacks each item from the tuple returned by get_date_values and passes them to the function. Since the tuple has three values, and check_date accepts three parameters, the * unpacks the tuple and passes each value to the function.
[1]: https://docs.python.org/3/library/calendar.html