Valid Date

Another good function which would come in handy for Zeller is a function to make sure the date which was inputted is valid and display a message if the program has encountered an invalid date. For this function I will be using my inArray function which I wrote in a previous post. I will utilise two arrays one with the months with 30 days and the other with the months with 31. My initial insight is as follows:

SET monthsThirty0 TO [4,6,7,11]
SET monthsThirty1 TO [1,3,5,7,8,10,12]
SET daysInMonth TO 0

IF inArray(month, monthsThirty0)
SET daysInMonth TO 30
ELSE IF inArray(month, monthsThirty1)
SET daysInMonth TO 30
ELSE IF there is no remainder of year/4
SET daysInMonth TO 29
ELSE
SET daysInMonth TO 28

IF day LESS THAN OR EQUAL TO daysInMonth
RETURN True
ELSE
RETURN False

This looks kinda of intense but it is easy enough to code, and I have managed to produce the following function:

def validDate(d, m, y):
    months_thirty0 = [4,6,7,11]
    months_thirty1 = [1,3,5,7,8,10,12]
    daysInMonth = 0

    if inArray(m, months_thirty0):
        daysInMonth = 30
    elif inArray(m, months_thirty1):
        daysInMonth = 31
    elif (y % 4) == 0:
        daysInMonth = 29
    else:
        daysInMonth = 28

    return (d <= daysInMonth)

Running this function on a number of dates produces the following results:

>>> validDate(31,6,2020)
False
>>> validDate(11,6,2020)
True
>>> validDate(29,2,2020)
True
>>> validDate(31,9,2020)
False

This is exactly what I set out to produce, the next step is to perform this step before any calculations in the Zeller code. The Resulting function is:

import math
from myfuncs import validDate

def zeller(day, month, year):
    days = ['Saturday', 'Sunday', 'Monday', 'Tuesday',
              'Wednesday', 'Thursday', 'Friday']
    if validDate(day, month, year):
        if month < 3:
            month = month + 12
            year = year -1
        calc = (day
                + math.floor((13*(month+1)/5))
                + year
                + math.floor(year/4)
                - math.floor(year/100)
                + math.floor(year/400)) % 7
        return days[calc]
    else:
        return 'Error Invalid Date'

Running the program with a invalid date and a valid date results in:

>>> zeller(31,9,2020)
'Error Invalid Date'
>>> zeller(19,5,1982)
'Wednesday'

This is exactly what I hoped would happen, an invalid date is caught and the calculation is not performed and an error returned otherwise the day of the week is returned.