We help IT Professionals succeed at work.

Need to up-date birth date validation javascript to check for valid date

egoselfaxis
egoselfaxis asked
on
I have the following javascript for validating a birth date:

function checkDate(myDate)
{
    re = /^\d{1,2}\-\d{1,2}\-\d{4}$/;
    return ( (myDate != '') && (!myDate.match(re)) );
}

However, .. this javascript function only verifies that the entered characters are numeric, and that they're in the format of "99-99-9999".  

I need to somehow update my function so that it also checks to verify that the entered date is valid, .. and  that it is NOT the current year OR or a year in the future (since the field is being used to enter people's birthdays).

For example, .. dates such as "13-32-2010" and "12-12-2011" should NOT be allowed.  Only valid calendar dates that are in a PAST YEAR should be allowed (ie: "06-11-2009").

( Before anyone suggests it -- we do NOT want to use a javascript-based calendar / datepicker.  The dates need to be manually entered. )

Can anyone here provide me with an updated javascript function that accomplishes the type of validation I've described?  Your help would be appreciated.  

Thanks!

- Yvan

Comment
Watch Question

Do like credit cards and have 3 drop-down lists, one for day, two for month, and three for year.  If you are uncomfortable with the years being too many, use the prefixes 194, 195, 196, 197, 198 etc.  Then all they do is type in the final letter of the year, and just make sure that is a single number.  This is a lot easier for you to handle, and it goes quick and intuitively for the user.  Ore else just have the 19 prefix and have them type in the last 2 numbers, and check them.
If you don't like that idea, here are some regex links to show how to validate birthdays --

http://www.java2s.com/Code/CSharp/Development-Class/Useregulartoverifyadate.htm
http://www.regular-expressions.info/dates.html
http://javascript.internet.com/forms/regexp-validation.html  (view source to see javascript regex)
Frederick McIntyreProgrammer

Commented:
The following should do the trick. Hope it meets your needs. It is a full html page (you can see it at http://www.achieversinternational.com/bdate.html)

Of course, pull out just the part you need. And you may want to pass in the value of the date differently. I do it this way so that if there is an error, I can put the cursor back in the field they need to correct. This does not allow a birth date with the current year, and it does not allow a birth date after the current date, and it does not allow a birth year more than 120 years ago. Adjust as you see fit.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <title>Validate Birth Date</title>

<script type="text/javascript">
function checkBD(obj) {
	if (obj.value == '') {
		alert('Please enter your birth day in the format m-d-yyyy.');
		obj.focus();
		return false;
	}
	// Pull mo,da,yr, etc from date they entered. RegExp.$1 is value in first () and
	// * 1 makes it a number. Allow for spaces before and after what they type.
	// We say mm-dd-yyyy but actually we can work with m-d-yyyy or m/d/yyyy or m d yyyy
	if (/^\s*(\d+)[-|\/| ]+(\d+)[-|\/| ]+(\d\d\d\d)\s*$/i.test(obj.value)) {
		mo = (RegExp.$1 * 1);
		da = (RegExp.$2 * 1);
		yr = (RegExp.$3 * 1);
	} else {
		alert('Please enter your birth day in the format m-d-yyyy.');
		obj.focus();
		return false;
	}
	if (mo < 1 || mo > 12) {
		alert('"' + mo + '" is not a valid entry for month.');
		obj.focus();
		return false;
	}
	// check days in month
	var dim = new Array(00,31,29,31,30,31,30,31,31,30,31,30,31);
	if (da > dim[mo] || da < 1) {
		alert('"' + da + '" is not a valid entry for day.');
		obj.focus();
		return false;
	}
	mo = (mo < 10) ? '0'+mo : mo;
	da = (da < 10) ? '0'+da : da;
	var dt = new Date();
	var dtyr = dt.getFullYear();
	var dtmo = dt.getMonth();
	var dtda = dt.getDate();
	dtmo = (dtmo < 10) ? '0'+dtmo : dtmo;
	dtda = (dtda < 10) ? '0'+dtda : dtda;
	// Is it this year?
	if (yr == dtyr) {
		alert('Sorry, we do not accept birth days in the current year.');
		obj.focus();
		return false;
	}
	// Do they claim to be ancient?
	if ((dtyr - yr) > 120) {
		alert('Sorry, people more than 120 years old are not acceptable.');
		obj.focus();
		return false;
	}
	// Crude but effective check for a date in the future.
	// change the numbers to strings so we concatenate, not add.
	var now = dtyr + '' + dtmo + '' + dtda + '';
	var bday = yr + '' + mo + '' + da + '';
	// multiply by 1 to change back to numbers.
	if ((bday * 1) > (now * 1)) {
		alert('Really now, are you sure you have not been born yet? Your birth date '+
			'cannot be in the future.');
		obj.focus();
		return false;
	}
	obj.value = mo+'-'+da+'-'+yr;
	alert('You entered a valid birth date: '+mo+'-'+da+'-'+yr);
}
</script>
 </head>
 <body>
Enter your birth date - month-day-year - then press tab:<br />
<input type="text" name="birthdate" onblur="checkBD(this); return false;" value="" />
  
 </body>
</html>

Open in new window

Frederick McIntyreProgrammer

Commented:
I should have noted, it will accept an entry with any combination of dash, slash, or space between the month, day and year. But it does require they be in that order. The script changes it to mm-dd-yyyy.

E.g., any of the following entries will work.
1/2/2009
1-2-2009
1 2 2009
1 / 2 / 2009
Programmer
Commented:
A check I forgot to do: If they enter February 29, check if it was indeed a leap year. Below is just the javascript with that check added.
<script type="text/javascript">
function checkBD(obj) {
	if (obj.value == '') {
		alert('Please enter your birth day in the format m-d-yyyy.');
		obj.focus();
		return false;
	}
	// Pull mo,da,yr, etc from date they entered. RegExp.$1 is value in first () and
	// * 1 makes it a number. Allow for spaces before and after what they type.
	// We say mm-dd-yyyy but actually we can work with m-d-yyyy or m/d/yyyy or m d yyyy
	if (/^\s*(\d+)[-|\/| ]+(\d+)[-|\/| ]+(\d\d\d\d)\s*$/i.test(obj.value)) {
		mo = (RegExp.$1 * 1);
		da = (RegExp.$2 * 1);
		yr = (RegExp.$3 * 1);
	} else {
		alert('Please enter your birth day in the format m-d-yyyy.');
		obj.focus();
		return false;
	}
	// Check if it is a leap year, if they claim February 29
	if (mo == 2 && da == 29) {
		if (!(((yr % 4 == 0) && (yr % 100 != 0)) || (yr % 400 == 0))) {
       alert(yr+' was not a leap year, so you could not have been born on February 29, '+yr);
			 obj.focus();
			 return false;
		}
	}
	if (mo < 1 || mo > 12) {
		alert('"' + mo + '" is not a valid entry for month.');
		obj.focus();
		return false;
	}
	// check days in month
	var dim = new Array(00,31,29,31,30,31,30,31,31,30,31,30,31);
	if (da > dim[mo] || da < 1) {
		alert('"' + da + '" is not a valid entry for day.');
		obj.focus();
		return false;
	}
	mo = (mo < 10) ? '0'+mo : mo;
	da = (da < 10) ? '0'+da : da;
	var dt = new Date();
	var dtyr = dt.getFullYear();
	var dtmo = dt.getMonth();
	var dtda = dt.getDate();
	dtmo = (dtmo < 10) ? '0'+dtmo : dtmo;
	dtda = (dtda < 10) ? '0'+dtda : dtda;
	// Is it this year?
	if (yr == dtyr) {
		alert('Sorry, we do not accept birth days in the current year.');
		obj.focus();
		return false;
	}
	// Do they claim to be ancient?
	if ((dtyr - yr) > 120) {
		alert('Sorry, people more than 120 years old are not acceptable.');
		obj.focus();
		return false;
	}
	// Crude but effective check for a date in the future.
	// change the numbers to strings so we concatenate, not add.
	var now = dtyr + '' + dtmo + '' + dtda + '';
	var bday = yr + '' + mo + '' + da + '';
	// multiply by 1 to change back to numbers.
	if ((bday * 1) > (now * 1)) {
		alert('Really now, are you sure you have not been born yet? Your birth date '+
			'cannot be in the future.');
		obj.focus();
		return false;
	}
	obj.value = mo+'-'+da+'-'+yr;
	alert('You entered a valid birth date: '+mo+'-'+da+'-'+yr);
}
</script>

Open in new window

Author

Commented:
Fredmc - this is fantastic.  Thank you so much!  It's important that I verify that there are only dashes between the different sets of numbers, however (spaces and slashes should NOT be allowed).  How might I adapt the script to check for that?


- Yvan
Frederick McIntyreProgrammer

Commented:
The script allows them to put in spaces or slashes (or dashes) but it changes it to only dashes. The script breaks down what they entered into month, day, and year, and puts it back into the field they typed it into as mm-dd-yyyy
Line 71
obj.value = mo+'-'+da+'-'+yr;

It also allows them to put in single digits for the month and day. (I have a real thing about lazy programmers that force you to type things the way they want it, rather than taking what you type and making it what they want!)

That said...
If you don't want to let them type in anything but the format mm-dd-yyyy or m-d-yyyy change line 11 to this:
       if (/^\s*(\d+)-(\d+)-(\d\d\d\d)\s*$/i.test(obj.value)) {

And if you want to force them to type in only two digit months and days, change line 111 to this:
       if (/^\s*(\d\d)-(\d\d)-(\d\d\d\d)\s*$/i.test(obj.value)) {
and change line 16 to
                alert('Please enter your birth day in the format mm-dd-yyyy.');

Personally, I like to be as kind to users as possible, but do as you wish. :-)
Frederick McIntyreProgrammer

Commented:
I accidently said "line 111" above. Obviously, it should have been "line 11"

Also I should have pointed out, it is lines 40 and 41 that assure there are two digits for month and day:
       mo = (mo < 10) ? '0'+mo : mo;  
        da = (da < 10) ? '0'+da : da;  
Since mo and da are numbers, not strings, you check for their value, not their length. If you aren't familiar with what those lines are doing, it is this:
Look at what's in parenthese after the equals sign. If it is true, assign what follows the question mark. If it is not true, assign what follows the colon.

Author

Commented:
You're absolutely right -- I hadn't even noticed those extra features.  This is perfect -- much better than what I asked for, actually.  Thanks again!

- yg