Validating date (both format and value)

I read this and got really interested: Validating date format using regular expression

so I started writing my own version of the date validation function, I think I am close, but not quite, and I would like some suggestion as well as tips. I have spend a lot of time trying to tweak the function.

import re
import datetime

# Return True if the date is in the correct format
def checkDateFormat(myString):
    isDate = re.match('[0-1][0-9]\/[0-3][0-9]\/[1-2][0-9]{3}', myString)
    return isDate

# Return True if the date is real date, by real date it means,
# The date can not be 00/00/(greater than today)
# The date has to be real (13/32) is not acceptable
def checkValidDate(myString):
    # Get today's date
    today = datetime.date.today()
    myMaxYear = int(today.strftime('%Y'))

    if (myString[:2] == '00' or myString[3:5] == '00'):
        return False

    # Check if the month is between 1-12
    if (int(myString[:2]) >= 1 or int(myString[:2]) <=12):
        # Check if the day is between 1-31
        if (int(myString[3:5]) >= 1 or int(myString[3:2]) <= 31):
            # Check if the year is between 1900 to current year
            if (int(myString[-4:]) <= myMaxYear):
                return True
    else:
        return False

testString = input('Enter your date of birth in 00/00/0000 format: ')

# Making sure the values are correct
print('Month:', testString[:2])
print('Date:', testString[3:5])
print('Year:', testString[-4:])

if (checkDateFormat(testString)):
    print('Passed the format test')
    if (checkValidDate(testString)):
        print('Passed the value test too.')
    else:
        print('But you failed the value test.')
else:
    print("Failed. Try again")

Question 1: Is there other way (better) to do int(myString[3:5]) when I want to compare if it is valid? I feel my method is very repetitive, and this function must require 00/00/0000, otherwise it will break. So the function isn't all that useful in that sense. Especially the way I handle my 00/01/1989, it is just simply comparing if they are indeed 00.

Question 2: There are many if statement, I wonder are there better way to write this test?

I would like to learn more about programming in python, any suggestion or advice will be greatly appreciated. Thank you very much.

Answers


Like many things in python there's already underlying capabilities to check dates. Assuming you aren't just doing this as an academic exercise the most straightforward way to validate a date is to try and create it.

import datetime

minyear = 1900
maxyear = datetime.date.today().year

mydate = '12/12/2000'
dateparts = mydate.split('/')
try:
    if len(dateparts) != 3:
       raise ValueError("Invalid date format")
    if int(dateparts[2]) > maxyear or int(dateparts[2]) < minyear:
       raise ValueError("Year out of range")
    dateobj = datetime.date(int(dateparts[2]),int(dateparts[1]),int(dateparts[0]))
except:
    // handle errors

if datetime.date is given an invalid date it will complain, eg:

datetime.date(2000,45,23)

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    datetime.date(2000,45,23)
ValueError: month must be in 1..12

I understand there's some value in academic exercises. I wouldn't discourage them.

I also think a big part of learning Python is discovering which problems have already been solved. There are several reasons I think this way. First, I think it's a waste of time to re-invent the wheel. Also I get a chance to study code and different approaches to solving problems. Finally, I think a long-standing solution is less likely to be naive about quirks in the subject matter.

With that in mind, I recommend the dateutil library.


from dateutil.parser import *
parse("1993-09-01")
datetime.datetime(1993, 9, 1, 0, 0)

If the format is not proper, then it will raise a ValueError, you can use try.. catch to catch them so that the application does not close unexpectedly.


Based on some answers above I wrote this short piece of code which validates date to in the format: DD/MM/YYYY.

date = "29/02/2016"

min_year = 1900
max_year = min_year + 200

days_31 = ['01', '03', '05', '07', '08', '10', '12']
days_30 = ['04', '06', '10', '11']
days_28 = ['02']

month_dict = {'01':'January',
      '02':'February',
      '03':'March',
      '04':'April',
      '05':'May',
      '06':"June",
      '07':'July',
      '08':'August',
      '09':'September',
      '10':'October',
      '11':'November',
      '12':'December'}

def validate(day, month, leap_year_or_not):
    if leap_year_or_not:
        max_day = 29
    else:
        max_day=28
    if month in days_28:
        if day > max_day:
            print "Invalid day: %s for month %s" %(day, month_dict[month])
            return False
        else:
            return True
    elif month in days_30:
        if day > 30:
            print "Invalid day: %s for month %s" %(day, month_dict[month])
            return False
        else:
            return True
    elif month in days_31:
        if day <= 31:
            return True
        else:
            print "Invalid day: %s for month %s" %(day, month_dict[month])
            return False
    else:
        print "Invalid month:%s, Invalid day:%s" %(month, day)
        return False

if len(date)!= 10:
    print "Invalid Format. Please enter date in DD/MM/YYYY"
else:
    day, month, year = date.split("/")
    if len(day) != 2:
        print "Length of day in not 2. Please enter day as 01 for first!" 
    elif len(month) != 2:
        print "Length of month in not 2. Please enter month as 01 for January!"
    elif len(year) != 4:
        print "Length of year in not 4. Please enter year as 2001!"
    else:
        day=int(day)
        month=int(month)
        year=int(year)
        if day < 1 or day > 31:
            print "Day %s is not in range [1-31]" %str(day)
        else:
            if month < 1 or month > 12:
                print "Month %s is not in range [1-12]" %str(month)
            else:
                if year < min_year or year > max_year:
                    print "Year is not in range [%s-%s]" (str(min_year), str(max_year))
            else:
                if year%4 == 0:
                    leap_year = True
                else:
                    leap_year = False
                valid_day_month = validate(day, str(month).zfill(2), leap_year)

import time
import datetime
self.date = raw_input('Enter the date to travel in (yyyy-mm-dd) format: ')
try:
    valid_date = time.strptime(self.date, '%Y-%m-%d')
    today_date=str(datetime.date.today())
    if self.date<today_date:
        print "date got over"
    else:
        print " "
except ValueError:
print('Invalid date!')

Need Your Help

CMS which is not a portal system

content-management-system repost portal-system

this is a repost of a question not correctly answered -- sorry about that.

How to resize view according to keyboard show/hide if keyboard is already shown

ios keyboard

In view A, I have a text field. I tap a control to push in a new view controller B. View B only has a text view whose frame should be adjusted to accommodate the keyboard, and I always set the text...