Saturday 1 December 2012

Validate & Verify a Date

When I say Verify, I mean make sure that it's in a correct format; this can very easily be accomplished using regex; if you don't know what that is, it's basically an expression to check formatting of a string against. I suggest reading the following site:

Zytrax this is an excellent source for regex knowledge, I use it regularly.

The following JavaScript function takes in a string and checks it against the following pattern ##/##/####. you may notice it doesn't make sure that the month is between 1-12 or the day is less then 31, it just makes sure that you entered 3 numbers and that they're separated by forward-slashes.

function validdateDate(dateString)
{
    var datePattern = /^\d{2}[/]\d{2}[/]\d{4}$/;
    return datePattern.test(dateString);
}

Now Validate, well that's a bit more tricky. First lets talk about what I mean by validate, if you run the date 02/29/2011 against a simple date Regex it will come back as valid, but it's clearly not since that date never occurred.

At first I thought I could just load the individual month day year into a constructor for a JavaScript Date object and just get an invalid date exception, but no such luck, lovely JavaScript  will just bump the date up to 03/01/2011. Good bad it doesn't really matter, what matters is that I still haven't validated my Date. It's high school programming time.

To resolve this issue first we need a function to check if we're dealing with a leap year, simple enough you can grab the algorithm from numerous sites; I got this one from Wikipedia or if your super lazy it's below.

function isLeapYear(year)
{
    if(year%400==0)
        return true;
    else if(year%100==0)
        return false;
    else if(year%4==0)
        return true;
    return false;
}

Now that we can tell if we're dealing with a leap year lets check to make sure that our date is an actual date. that has occurred.

function verifyDate(dateString)
{
    var daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];

    if(dateString.length != 10)
        return false;

    var da = dateString.split("/");
  
    if(da[2] <= new Date().getFullYear())
    {
        if(da[0] > 0 && da[0] < 13)
        {
            if(da[0] == 2 && isLeapYear(da[2]))
                return (da[1] > 0 && da[1] < 30);
            else
                return (da[1] > 0 && da[1] < daysInMonth[da[0]-1]);
        }
    }
    return false;
}

Well there you have it, are there other much more robust ways to check date, sure there are, could I have written this function to take in some sort of pattern to check against rather then just month/day/year, absolutely, but i'm not writing an API, I'm just making a one off function to filter out shitty data before it hits my server.