Date validation

John Machin sjmachin at lexicon.net
Fri Apr 25 22:37:08 EDT 2003


James Gregory <james at anchor.net.au> wrote in message news:<mailman.1051255479.31840.python-list at python.org>...
> Hi all,
> 
> I'm writing a killer web app in python and I want to validate all the
> input it gets. Amongst said input are dates represented as text strings
> of the format 'YYYY-MM-DD' - how can I check whether or not such strings
> represent a valid date? I had thought that

While the others are arguing about what to do with their knuckles, here's some code:

# dateok.py

days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
#                    J   F   M   A   M   J   J   A   S   O   N   D

def leap(year):
   if year % 4: return 0
   if year % 100: return 1
   return year % 400 == 0
   
MIN_YEAR = 1800
MAX_YEAR = 2200
# suit yourself ...

def dateok(y, m, d):
   if not MIN_YEAR <= y <= MAX_YEAR: return 0
   if not 1 <= m <= 12: return 0
   if m == 2 and leap(y):
      lastday = 29
   else:
      lastday = days_in_month[m]
   return 1 <= d <= lastday

test_data_strg = """
2201 01 01 0
2200 12 31 1
1800 01 01 1
1799 12 31 0
2000 31 12 0
2000 12 31 1
2000 00 01 0
2000 02 29 1
2004 02 29 1
2001 02 29 0
2100 02 29 0
1900 02 29 0
2001 01 31 1
2001 02 31 0
2001 03 31 1
2001 04 31 0
2001 05 31 1
2001 06 31 0
2001 07 31 1
2001 08 31 1
2001 09 31 0
2001 10 31 1
2001 11 31 0
2001 12 31 1
2001 01 32 0
2001 02 32 0
2001 03 32 0
2001 04 32 0
2001 05 32 0
2001 06 32 0
2001 07 32 0
2001 08 32 0
2001 09 32 0
2001 10 32 0
2001 11 32 0
2001 12 32 0
2001 01 30 1
2001 02 30 0
2001 03 30 1
2001 04 30 1
2001 05 30 1
2001 06 30 1
2001 07 30 1
2001 08 30 1
2001 09 30 1
2001 10 30 1
2001 11 30 1
2001 12 30 1
2001 02 28 1
2001 01 00 0
2001 01 -1 0
2001 01 -2 1
"""
# The last entry is deliberate to show that the 
# testing mechanism actually does detect errors

if __name__ != "__main__":
   del test_data_strg
else:
   print
   npass = 0
   nfail = 0
   for line in test_data_strg.splitlines():
      if not line.strip(): continue
      y, m, d, expected = map(int, line.split())
      actual = dateok(y, m, d)
      if actual == expected:
         npass += 1
      else:
         nfail += 1
         print "dateok(%d, %d, %d) -> %d, expected %d" % (y, m, d, actual, expected)
   print
   print "Passed: %d, Failed: %d" % (npass, nfail)

 ... and not a class in sight, let alone a metaclass.

HTH,
John




More information about the Python-list mailing list