Solved

Javascript Date Validation

Posted on 2004-08-11
23
2,132 Views
Last Modified: 2012-06-27
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.

0
Comment
Question by:Isaac
  • 9
  • 4
  • 3
  • +4
23 Comments
 
LVL 4

Expert Comment

by:marko020397
ID: 11777913
Try to make users input the date via popup: http://www.mattkruse.com/javascript/calendarpopup/
0
 
LVL 36

Expert Comment

by:Zyloch
ID: 11778006
Hi

You allow '/' between fields right?

Regards,
Zyloch
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11778177
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
 
LVL 63

Expert Comment

by:Zvonko
ID: 11778262
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
 
LVL 5

Expert Comment

by:darksinclair
ID: 11778385
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
 
LVL 5

Expert Comment

by:darksinclair
ID: 11778408
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
 
LVL 63

Expert Comment

by:Zvonko
ID: 11778871
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
 
LVL 36

Expert Comment

by:Zyloch
ID: 11779440
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
 
LVL 14

Expert Comment

by:ziffgone
ID: 11779690
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
 
LVL 14

Expert Comment

by:ziffgone
ID: 11779711
@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
 
LVL 2

Expert Comment

by:ngrover
ID: 11779721
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 2

Expert Comment

by:ngrover
ID: 11779726
Ziffgone beat me to it with a full script too.  Didn't see the post or I would have not rambled.
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11781077
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
 
LVL 36

Expert Comment

by:Zyloch
ID: 11781093
Thanks :)
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11781121
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
 
LVL 36

Expert Comment

by:Zyloch
ID: 11781191
If I did, I don't remember. As to regarding the time zones, is it 3 am at your place?
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11781727
Uhps! No, I am located in Munich. It is short after 11am. Time to go to lunch :-)
0
 
LVL 5

Author Comment

by:Isaac
ID: 11794459
OK you guys. I'm back and I'll start checking these suggestions.
Thanks.
0
 
LVL 5

Author Comment

by:Isaac
ID: 11809956
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
 
LVL 63

Expert Comment

by:Zvonko
ID: 11810271
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
 
LVL 5

Author Comment

by:Isaac
ID: 11812387
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
 
LVL 63

Accepted Solution

by:
Zvonko earned 500 total points
ID: 11814672
Then extend the checking to this:

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

Expert Comment

by:Zvonko
ID: 11825337
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

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Today I would like to talk about localizing (Internationalization) JavaScript applications. Introduction When creating an application that is going to be used by many people around the globe, it is important to remember that not everyone speak…
Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now