5

I have a javascript function that checks for a date range. Is there any way to check if a user has input a valid date in a textbox, regardless of format?

function checkEnteredDate() {
            var inputDate = document.getElementById('txtDate');
            //if statement to check for valid date
            var formatDate = new Date(inputDate.value);
            if (formatDate > TodayDate) {
                alert("You cannot select a date later than today.");
                inputDate.value = TodayDate.format("MM/dd/yyyy");
            }
}
MrM
  • 21,709
  • 30
  • 113
  • 139

5 Answers5

9

take a look at this library date.js http://code.google.com/p/jqueryjs/source/browse/trunk/plugins/methods/date.js

it has a useful function called fromString which will try and convert a string (based on Date.format) to a valid date object.

the function returns false if it doesn't create a valid date object - you can then try a different format before giving up if all return false.

here are some example formats you could test for:

Date.format = 'dd mmm yyyy';
alert(Date.fromString("26 Jun 2009"));

Date.format = 'mmm dd yyyy';
alert(Date.fromString("Jun 26 2009"));

Date.format = 'dd/mm/yy';
alert(Date.fromString("26/06/09"));

Date.format = 'mm/dd/yy';
alert(Date.fromString("06/26/09"));

Date.format = 'yyyy-mm-dd';
alert(Date.fromString("2009-06-26"));

Josh

Josh
  • 6,256
  • 2
  • 37
  • 56
  • Unless the user specifies the format, you'll still have the europe/US ambiguity problem. – Matt Bridges Jul 02 '09 at 13:27
  • @Matt - correct - the only solution for this is to test if the days or months are greater that 12 - if not you have to return that the date is ambiguous and they should use dd/mm/yyyy – Josh Jul 02 '09 at 13:57
4

It is an awfully tricky problem to parse dates in an arbitrary format (as @Natrium points out). It's even more confusing when you consider that europe writes their dates as dd/mm/yyyy, so you can't tell if 2/7/09 is February 7th or July 2nd.

Most people tackle this problem by either using a datepicker type of control from a javascript library, or by using dropdown boxes with set values for month, day, and year.

<select name="month">
<option value="1">January</option>
<option value="2">February</option>
...
<option value="12">December</option>
</select>

<select name="day">
<option value="1">1</option>
<option value="2">2</option>
...
<option value="31">31</option>
</select>

<select name="year">
<option value="2000">2000</option>
<option value="2001">2001</option>
...
<option value="2009">2009</option>
</select>
Matt Bridges
  • 48,277
  • 7
  • 47
  • 61
  • Using selects is an awful solution. Now instead of typing "27" for day, I need to scroll down a whole list of numbers - the pulldown will open into a narrow tall rectangle on most platforms which is difficult to manage. On the other hand, having non-select based controls still subjects you to the parsing problem. – levik Jul 02 '09 at 14:34
  • 1
    Actually, if you tab to the select field then type "2" then "7" it will correctly pick "27." (Tested using firefox). – Matt Bridges Jul 02 '09 at 16:20
3

regardless of format?

that will be tricky...

  • 2009/07/02 is a valid date
  • 02/07/09 also
  • 2-7-09 also
  • 02-7-'09 also
  • the second of July 2009 --> also valid
  • twee juli tweeduizend en negen --> also valid (Dutch language)

All valid, but all with a different format. So, regardless of format... I seriously doubt it...

Natrium
  • 30,772
  • 17
  • 59
  • 73
2

You can regular expression or a custom made code. Example below:

function isValidDate(dateStr, format) {
   if (format == null) { format = "MDY"; }
   format = format.toUpperCase();
   if (format.length != 3) { format = "MDY"; }
   if ( (format.indexOf("M") == -1) || (format.indexOf("D") == -1) || _
      (format.indexOf("Y") == -1) ) { format = "MDY"; }
   if (format.substring(0, 1) == "Y") { // If the year is first
      var reg1 = /^\d{2}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
      var reg2 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/
   } else if (format.substring(1, 2) == "Y") { // If the year is second
      var reg1 = /^\d{1,2}(\-|\/|\.)\d{2}\1\d{1,2}$/
      var reg2 = /^\d{1,2}(\-|\/|\.)\d{4}\1\d{1,2}$/
   } else { // The year must be third
      var reg1 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{2}$/
      var reg2 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/
   }
   // If it doesn't conform to the right format (with either a 2 digit year or 4 digit year), fail
   if ( (reg1.test(dateStr) == false) && (reg2.test(dateStr) == false) ) { return false; }
   var parts = dateStr.split(RegExp.$1); // Split into 3 parts based on what the divider was
   // Check to see if the 3 parts end up making a valid date
   if (format.substring(0, 1) == "M") { var mm = parts[0]; } else _
      if (format.substring(1, 2) == "M") { var mm = parts[1]; } else { var mm = parts[2]; }
   if (format.substring(0, 1) == "D") { var dd = parts[0]; } else _
      if (format.substring(1, 2) == "D") { var dd = parts[1]; } else { var dd = parts[2]; }
   if (format.substring(0, 1) == "Y") { var yy = parts[0]; } else _
      if (format.substring(1, 2) == "Y") { var yy = parts[1]; } else { var yy = parts[2]; }
   if (parseFloat(yy) <= 50) { yy = (parseFloat(yy) + 2000).toString(); }
   if (parseFloat(yy) <= 99) { yy = (parseFloat(yy) + 1900).toString(); }
   var dt = new Date(parseFloat(yy), parseFloat(mm)-1, parseFloat(dd), 0, 0, 0, 0);
   if (parseFloat(dd) != dt.getDate()) { return false; }
   if (parseFloat(mm)-1 != dt.getMonth()) { return false; }
   return true;
}
Bhaskar
  • 10,537
  • 6
  • 53
  • 64
0

I realize I have to get a validation on the code behind. These are all good answers, but was starting to get complicated. I didnt want to back myself in a corner so I choose the alternate route. Thanks

MrM
  • 21,709
  • 30
  • 113
  • 139