Javascript Date Validation

Hello All,

I want to validate a date field on the form that has the format: "dd mmm yyyy"
I don't want users to enter in the wrong date format.

Thanks for your help.

LVL 5
IsaacSharePoint Client Side DeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

marko020397Commented:
Try to make users input the date via popup: http://www.mattkruse.com/javascript/calendarpopup/
0
ZylochCommented:
Hi

You allow '/' between fields right?

Regards,
Zyloch
0
ZvonkoSystems architectCommented:
Here my version:

<html>
<head>
<script>
month = "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dec".split(",");
function checkDate(theField){
  dPart = theField.value.split(" ");
  if(dPart.length!=3){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.focus();
    return false;
  }
  for(i=0;i<month.length;i++){
    if(dPart[1].toLowerCase()==month[i].toLowerCase()){
      dPart[1]=i;
      break;
    }
  }
  nDate = new Date(dPart[2], dPart[1], dPart[0]);
  if(isNaN(nDate) || dPart[2]!=nDate.getFullYear() ||
      dPart[1]!=nDate.getMonth() || dPart[0]!=nDate.getDate()){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.select();
    theField.focus();
    return false;
  } else {
    return true;
  }
}
</script>
</head>
<body>
<form>
Date:
<input type=text name="someDate" onBlur="return checkDate(this)">
</form>
</body>
</html>

0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

ZvonkoSystems architectCommented:
This version uppercase the first character in the Month:

<html>
<head>
<script>
month = "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dec".split(",");
function checkDate(theField){
  dPart = theField.value.split(" ");
  if(dPart.length!=3){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.focus();
    return false;
  }
  for(i=0;i<month.length;i++){
    if(dPart[1].toLowerCase()==month[i].toLowerCase()){
      dPart[1]=i;
      break;
    }
  }
  nDate = new Date(dPart[2], dPart[1], dPart[0]);
  if(isNaN(nDate) || dPart[2]!=nDate.getFullYear() ||
      dPart[1]!=nDate.getMonth() || dPart[0]!=nDate.getDate()){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.select();
    theField.focus();
    return false;
  } else {
    theField.value = nDate.getDate()+" "+month[dPart[1]]+" "+nDate.getFullYear();
    return true;
  }
}
</script>
</head>
<body>
<form>
Date:
<input type=text name="someDate" onBlur="return checkDate(this)">
</form>
</body>
</html>

0
darksinclairCommented:
I created a very simple date validation a while back... Its really simple to follow and easy to use.  However, I'm sure Zvonko's posts before me are much more powerful and robust.  

Here's the code if it helps any,

function validate()
{
form = document.forms[0];

var error
  error = false;
var msg
  msg = "The following Fields are Required : \n";

// Error checks all dates (if they are entered) and the required fields.
for( i = 0; i < form.elements.length; i++ )
{
   var strName;
   strName = form.elements[i].name;
                  
   var iPosition;
     iPosition = strName.indexOf("_date");
            
   if( iPosition != -1 && form.elements[i].value != "" )
   {
      var day
      var month
      var year
      var toCheck
         toCheck = form.elements[i].value.split("/");
                  
      if( toCheck == null || isNaN( toCheck[0] ) || isNaN( toCheck[1] ) || isNaN( toCheck[2] ) )
      {      
         alert( "ERROR! Date is invalid for entered " + form.elements[i].name + ".  Entries must be of the form dd mm yyyy ONLY." );
         window.form.elements[i].focus();
         window.form.elements[i].select();
         return( false );      
      }
      else
      {  
         month = toCheck[0]
         day = toCheck[1]
         year = toCheck[2]
                        
         if( year % 4 == 0 )
         {      leap = true;      }
                        
         if( month == 2 )
         {
         if( leap == true )
            if( day < 0 || day > 29 )
            {      
                alert( "ERROR!  Date specified is out of acceptable range for February." );
      return( false );
            }
            else
               if( day < 0 || day > 28 )  
               {
                  alert( "ERROR!  Date Specified is out of acceptable range for February." );
                  return( false );
               }    
            }
            else
            {
               if( ( month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ) && ( day < 0 || day > 31 ) )
               {
                  alert( "ERROR!  Date Specified is out of acceptable range.\nThere is no Day " + day + " in month : " + month + "." );
                  return( false );
               }
               else if( ( month == 4 ||month == 6|| month == 9|| month == 11 ) && (day < 0 || day > 30) )
               {
                  alert( "ERROR!  Date Specified is out of acceptable range.\nThere is no Day " + day + " in " + month + "." );
                  return( false );
               }
               else if( !(1 <= month <= 12) )
               {
                  alert( "ERROR!  Date Specified is out of acceptable range.\nThe month '" + month + "' is invalid." );
                  return( false );          
               }
         }
     }
}
0
darksinclairCommented:
Woops!

toCheck = form.elements[i].value.split("/");

Should be : toCheck = form.elements[i].value.split(" ");

and
         month = toCheck[0]
         day = toCheck[1]
         year = toCheck[2]

Should Be :

         month = toCheck[1]
         day = toCheck[0]
         year = toCheck[2]

My Mistake. :(
0
ZvonkoSystems architectCommented:
Thanks for compliments :-)

My strategy with Dates is to let the built in JavaScript "new Date()" check for February and other months days count.
That simplifies the code dramaticaly.
0
ZylochCommented:
I have a much better strategy with dates that saves plenty of time and it is.....
...use Zvonko's code (I know this would've been much more effective if I left like 10 blank spaces in between, but who knows how much space those extra new lines will take up on the database...
0
ziffgoneCommented:
Here's my version,

This version will allow any splitter, (example: "11/Aug/2004", "11,Aug,2004","11 Aug 2004").

It will also allow full month names to be written, ("August" instead of "Aug". Also allows any case: "august" or "aug")

And, if the date is written in the correct order and valid, it will return an output of "dd Mmm yyyy".

One more thing, it will output "june", "july" and "september" as "June", "July" and "Sept" respectively. (I think they read better that way, and is more commom as the four letter months are seldom abbreviated and September is most commonly abbreviated to "Sept".

Code:-----------------------------------------------------------
<HTML>
<HEAD>
<TITLE>ScriptLibrary!</TITLE>

<script LANGUAGE="JavaScript">
<!-- Begin
var month = new Array('january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december');
var isValid = 0;
function Not_Valid(){
     document.form1.IntrDate.select();
     document.form1.IntrDate.focus();
     alert('Please enter the date in the following format: dd/mmm/yyyy');
}
var datin = new Array();
function Valid_Date(datein){
        document.form1.IntrDate.value = datein.replace(/\W/g, '\ ');
        datein = datein.split(/\W/);
        if((!isNaN(datein[0])) && datein[0].length < 3){
                   if((datein[0] > 0) && (datein[0] < 32)){
                        isValid += 1;
                   }
                   else{
                        isValid = 0;
                   }
        }    
        else{
             isValid = 0;
        }
        if(datein[1].match(/\w/)){
                datein[1] = datein[1].toLowerCase();
                datein[1] = "^"+datein[1];
                for(i=0;i<month.length;i++){
                     if((month[i].match(datein[1])) && (datein[1].length > 2)){
                          var isMonth=true;
                          datein[1] = datein[1].replace("\^","");
                       /* Remove if 3 letter Month Abbreviation wanted only */
                             if((datein[1].indexOf("jun") == 0) || (datein[1].indexOf("jul") == 0) || (datein[1].indexOf("sep") == 0)){
                                 if(datein[1].indexOf('jun') == 0){
                                      datein[1] = "june";
                                 }
                                 else if(datein[1].indexOf('jul')== 0){
                                      datein[1] = "july";
                                 }
                                 else{
                                      datein[1] = "sept";
                                 }
                                      var lgth = 4;
                             }
                            else{
                                 var lgth = 3
                            }
                       /* end remove section */
                          var caps = datein[1].slice(0,1);
                          caps = caps.toUpperCase();
                          datein[1] = datein[1].slice(1,lgth);
                          caps += datein[1];
                          datein[1] = caps;
                     }
                }
                if(isMonth){
                     isValid += 1;
                }
                else{
                     isValid = 0;
                }    
        }
        else{
             isValid = 0;
        }
        if(datein[2].match(/\d/)){
             if(datein[2].length == 4){
                  isValid += 1;
             }
             else{
                  isValid = 0;
             }
        }
        else{
             isValid = 0;
        }
    if(isValid == 3){
             document.form1.IntrDate.value = datein[0]+' '+datein[1]+' '+datein[2];
             isValid = 0;
    }
    else{
        Not_Valid();
        return false;
    }
}
// End -->
</script>
</HEAD>
<BODY BGCOLOR="#ffffff" link="#CC0033" vlink="#333399" alink="#FF0000">
<TABLE BORDER="0" CELLSPACING="5" CELLPADDING="5">
<TR><TD>
<FONT FACE="ARIEL,HELVETICA" SIZE="-1">

<P><FONT COLOR="#003399" FACE="ARIEL,HELVETICA" SIZE="-1"><B>Live Demo: Date Validation</B></FONT></P>

<form name="form1" action="#" onsubmit="Valid_Date(this.IntrDate.value);return false;">
  <p>Enter a date in format (dd mmm yyyy) :<input LANGUAGE="JavaScript" TYPE="text" SIZE="20" NAME="IntrDate" VALUE=""> </p>
  <p><input type="submit" value="Check date" name="B1"></p>
</form>
</FONT>
</TD></TR>
</TABLE>
</BODY>
</HTML>

End Code:-----------------------------------------------------------

If you want to only return a three letter month abbreviation no matter what, simply replace this section:

/* Remove below section if 3 letter Month Abbreviation wanted only */
if((datein[1].indexOf("jun") == 0) || (datein[1].indexOf("jul") == 0) || (datein[1].indexOf("sep") == 0)){
                                 if(datein[1].indexOf('jun') == 0){
                                      datein[1] = "june";
                                 }
                                 else if(datein[1].indexOf('jul')== 0){
                                      datein[1] = "july";
                                 }
                                 else{
                                      datein[1] = "sept";
                                 }
                                      var lgth = 4;
                             }
                            else{
                                 var lgth = 3;
                            }
/* end remove section */

With this:

var lgth = 3;

That's about it.

Regards...
 
0
ziffgoneCommented:
@Zyloch

 - "but who knows how much space those extra new lines will take up on the database..."

I believe it's 4 bytes per blank line.

Regards...
0
ngroverCommented:
Why force mm/dd/yyyy when you can use regular expressions and a little more code to allow a wide range of input types and convert it to mm/dd/yyyy for them?

Let's say you want to allow mm dd yyyy with any delimiter, and you also want to allow user to type in month names, either before the date or after the date, with year being optional and you plan to assume current year if they don't enter one.

This is much easier than you'd think.

try this:

reg1 = /^\D*\d{1,2}\D+\d{1,2}(\D+(\d{2}|\d{4}))?\D*$/
reg1a = /^\D*\d{1,2}\D+\d{1,2}\D+(\d{2}|\d{4})?\D*$/

reg1 is for the delimited digits format (mm ? dd ? yyyy)  allowing any delimiter, of any length, as long as it doesn't contain a digit.  So "04^--29/  2004" is a valid date,  so is "04?29?2001" and
"9 12".  

Reg1a checks for a year value on the end.  If the year appears, use that, otherwise you use current year.

reg2 = /jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/i

This will identify a month name string, both short and long.  You could get REALLY fancy and allow for typos etc but I won't get into that for now.

Once you've found a string that has a month name string in it, you have to see if you're dealing with month first, or date then month.  (and then optional year).

If you find a match, then use these two to see if you have a 'dd MMM' or 'MMM dd' format:

reg3 = /[a-zA-Z]{3}\D+\d{2}\D*/

This will identify an instance of 3 letters followed by one or more nondigits followed by two digits followed by one or more nondigits.

So.... "  Febxruary -- 14 " is a valid date.
And "  March 12  , - 2001 ".
Unfortunately, this is valid too:  "Jun 910001" which is close to being nonsense.   A little tweaking is all it takes to fix this though, if you are serious about flexible date validation.

Not valid:  "Ju ne 23 2004".

reg4 = /\d{2}\W+[a-zA-Z]{3}/

This will find an instance of 2 digits followed by one or more of any characters not a number or letter, followed by 3 letters.

So...   "x14 - Febxruary " is valid.
So is " 12..march..2000.."
And  "23 june"

But this is invalid:  "  23 ju-ne "

Now you know if it's dd MMM or MMM dd.   Parse appropriately and build yourself a data object from the values, the reset the field to the format you want (mm/dd/yyyy) in your case.

Yes, it's more work.  But that's not an excuse for making it harder on your users.   And your users will be blown away by how smart your date validation is.

I have a script that does all this and a bit more if you're interested.  Unfortunately, at this point, it's a little too long for public facing websites (12k) just to validate a date.

nate grover
0
ngroverCommented:
Ziffgone beat me to it with a full script too.  Didn't see the post or I would have not rambled.
0
ZvonkoSystems architectCommented:
This one is for Zyloch ;-)

<html>
<head>
<script>
month = "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dec".split(",");
function checkDate(theField){
  dPart = theField.value.split(/\W+/);
  if(dPart.length!=3){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.focus();
    return false;
  }
  for(i=0;i<month.length;i++){
    if(dPart[1].toLowerCase()==month[i].toLowerCase()){
      dPart[1]=i;
      break;
    }
  }
  nDate = new Date(dPart[2], dPart[1], dPart[0]);
  if(isNaN(nDate) || dPart[2]!=nDate.getFullYear() ||
      dPart[1]!=nDate.getMonth() || dPart[0]!=nDate.getDate()){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.select();
    theField.focus();
    return false;
  } else {
    theField.value = nDate.getDate()+" "+month[dPart[1]]+" "+nDate.getFullYear();
    return true;
  }
}
</script>
</head>
<body>
<form>
Date:
<input type=text name="someDate" onBlur="return checkDate(this)">
</form>
</body>
</html>

0
ZylochCommented:
Thanks :)
0
ZvonkoSystems architectCommented:
Oh, we are in the same time zone :)
Did you post your Date checking method on EE before? Was that an one-liner RegExp with leap year checking?
0
ZylochCommented:
If I did, I don't remember. As to regarding the time zones, is it 3 am at your place?
0
ZvonkoSystems architectCommented:
Uhps! No, I am located in Munich. It is short after 11am. Time to go to lunch :-)
0
IsaacSharePoint Client Side DeveloperAuthor Commented:
OK you guys. I'm back and I'll start checking these suggestions.
Thanks.
0
IsaacSharePoint Client Side DeveloperAuthor Commented:
zvonko,

How can I integrate your code into what I already have?

This is the validation I have for other fields:
<!--
function sub_onSubmit()
{
      var form = document.sub;
      var controlCounter;
      var returnValue = true;
      var formControl;
      
      if ( form.INDIVIDUAL.selectedIndex == 0 )
          {
              alert ( "Please make a selection for individual." );
                  form.INDIVIDUAL.focus();
                  return false;
            }
            
      if ( form.sub_Title.value == "" )
            {
              alert ( "Please make a selection for Title." );
                  form.sub_Title.focus();
                  return false;
            }
}

<form name="subject" METHOD="post" ACTION="procAddSubject.cfm" onSubmit="return subject_onSubmit(this)">
.... REST OF THE FORM ....
0
ZvonkoSystems architectCommented:
Like this:

<html>
<head>
<script>
function subject_onSubmit(theForm){
     var controlCounter;
     var returnValue = true;
     var formControl;
     
     if (theForm.INDIVIDUAL.selectedIndex == 0 )
         {
             alert ( "Please make a selection for individual." );
             theForm.INDIVIDUAL.focus();
             return false;
          }
         
     if (theForm.sub_Title.value == "" )
          {
             alert ( "Please make a selection for Title." );
             theForm.sub_Title.focus();
             return false;
          }
     if(checkDate(theForm.someDate)==false){
             return false;
     }
}

function checkDate(theField){
  month = "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dec".split(",");
  dPart = theField.value.split(/\W+/);
  if(dPart.length!=3){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.focus();
    return false;
  }
  for(i=0;i<month.length;i++){
    if(dPart[1].toLowerCase()==month[i].toLowerCase()){
      dPart[1]=i;
      break;
    }
  }
  nDate = new Date(dPart[2], dPart[1], dPart[0]);
  if(isNaN(nDate) || dPart[2]!=nDate.getFullYear() ||
      dPart[1]!=nDate.getMonth() || dPart[0]!=nDate.getDate()){
    alert("Enter Date in this format: dd mmm yyyy");
    theField.select();
    theField.focus();
    return false;
  } else {
    theField.value = nDate.getDate()+" "+month[dPart[1]]+" "+nDate.getFullYear();
    return true;
  }
}
</script>
</head>
<body>
<form name="subject" METHOD="post" ACTION="procAddSubject.cfm" onSubmit="return subject_onSubmit(this)">
<input type=text name="INDIVIDUAL" value="xx">
<input type=text name="sub_Title" value="xx">
<input type=text name="someDate" value="">
<input type=submit>
</form>
</body>
</html>

0
IsaacSharePoint Client Side DeveloperAuthor Commented:
ZVONKO,

It works perfectly.  Just one problem.
On my form I have about 8 date fields and not all of them are required.
When I use your code and I hit submit, I get prompted if there is a date field that I purposefully left blank.

Thanks.
0
ZvonkoSystems architectCommented:
Then extend the checking to this:

     if(theForm.someDate.value>"" && checkDate(theForm.someDate)==false){
             return false;
     }
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ZvonkoSystems architectCommented:
Thanks for the points.
If you want to do me a favour then please drop also a line into Feedback form.
Click simply the label "Feedback" next to my member name above my comments.
Thanks in advance, Zvonko
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.