Skip to main content
3 of 3
add more commentary

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 via if len(list) > 0, but you can do if 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.