I know this is a part of an exercise, but it feels like a lot of wheel reinventing where you can leverage builtin Python capabilities for date validation:
from datetime import date
>>> date(2020, 2, 29) # leap year date works
datetime.date(2020, 2, 29)
>>> date(2002, 2, 29) # non-leap year will raise ValueError
ValueError: day is out of range for month
>>> date(2002, 9, 31) # 31th day will raise ValueError
ValueError: day is out of range for month
instead of creating 3 separate lists for years, months and days, you can create only one list, since you always access these parts at the same index. That also simplifies the
for
loop which gives you the values directly instead of giving you an index you want to access in these lists.Python is a dynamic language where empty collections are evaluated to
False
, so when you want to check if a list has any items, you don't have to do it explicitly viaif len(list) > 0
, but you can doif list:
. For purpose of printing items in list, you can take it one step further and omit the condition completely as iterating through an empty list wont print anything. Snippet before/after:
# before
if len(dates) > 0:
for date in dates:
print(date)
# after
for date in dates:
print(date)
all suggestion applied:
import re
from datetime import date
def date_detector(text):
date_pattern = re.compile('''
([12][0-9]|3[0-1]|0?[1-9]) # to detect days from 1 to 31
([./-]) # to detect different separations
(1[0-2]|0?[1-9]) # to detect number of months
([./-]) # to detect different seperations
(2?1?[0-9][0-9][0-9]) # to detect number of years from 1000-2999 years
''', re.VERBOSE)
# use only one list for storing all parts of match together
parsed = []
for match in date_pattern.findall(text):
# year, month, day for easier passing to date()
parsed.append([ int(match[4]), int(match[2]), int(match[0])] )
valid = []
for item in parsed:
try:
# pass list of [year, month, day] to date() and let it check its validity for us
date(*item)
except ValueError as e:
pass # invalid date, dont do anything
else:
valid.append(item)
for item in valid:
print(item)
data = '30-06-2012, 31-12-2012, 15-02-2002, 29-02-2004, 29-02-2002, 31-02-2004, 31-06-2012'
date_detector(data)
- this can be simplified further by merging both
for
loops together, so you it does not iterate through the collection of data twice needlessly.