0

I am searching for a way to validate Date/Time formats in the following format:

  • ddHHmmZ MMM yy (example: 091603Z Apr 14)

The validator must only accept valid datetimes.

I have following regEx in place:

var militaryDateTime =
    /^\s*(\d{1,2})(\d{1,2})(\d{1,2})[zZ]{1}\s+([a-zA-Z]{3})\s+(\d{2})\s*$/;

The above only validates that the alpha/numeric chunks of the datetime are in the correct spot. How can I extend this to check for valid date/times?

collapsar
  • 15,446
  • 3
  • 28
  • 56
codeg
  • 223
  • 1
  • 4
  • 20
  • Just a question... are you using some server side framework? preferably asp.net mvc :) I am validating the dates on the server, because is very buggy to do it on client side. – Catalin Apr 09 '14 at 16:24
  • Yes, we are using asp.net mvc. One of our reqs is to validate both client/server side. – codeg Apr 09 '14 at 16:25
  • Does this need to be done with regexes? I'd suggest using [moment.js](http://momentjs.com/) and have it parse the string with the specified format. If it returns a valid object, then the date was valid. – Rocket Hazmat Apr 09 '14 at 16:27
  • 1
    If you have the field on a form, you can add the `[Remote]` attribute, and make an `ActionResult` where you can try something like `DateTime.TryParseExact("091603Z Apr 14", "ddHHmmZ MMM yy", CultureInfo.CurrentCulture, DateTimeStyles.None, out date)` – Catalin Apr 09 '14 at 16:28
  • Brilliant! I am trying the [Remote] attribute approach as the datetime field is on the form. – codeg Apr 09 '14 at 16:34

3 Answers3

3

Rather than making a complicated regex, you could use a third party library to validate your date format. I would suggest MomentJS.

var format = "DDHHmm MMM YY";
var dates = [
    "091500 Jan 14", // Valid date
    "321500 Jan 14", // Invalid day
    "092500 Jan 14", // Invalid hour
    "091561 Jan 14", // Invalid minute
    "091500 LOL 14"  // Invalid month
];

for(var i in dates) {
    if(moment(dates[i], format).isValid()){
        alert("\"" + dates[i] + "\" is valid");
    } else {
        alert("\"" + dates[i] + "\" is not Valid");
    }
}

I posted a live demo to fiddle too: http://jsfiddle.net/txHnt/1/

TJ Kirchner
  • 4,269
  • 6
  • 22
  • 26
1

The best way to do this without any plugins or libraries is to first grab all the datetime components via RegEx to test if the input string is formatted correctly in the first place:

var test_str = '091603Z Apr 14';
var date_matches = test_str.match(/^(\d{2})(\d{2})(\d{2})Z (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2})$/);
// date_matches = ["091603Z Apr 14", "09", "16", "03", "Apr", "14"];

Then parse a correctly formatted/compiled string that Date.parse can properly parse:

var s = Date.parse(date_matches[4] + ' ' + date_matches[1] + ', ' + date_matches[5] + ' ' + date_matches[2] + ':' + date_matches[3]);
// s = 1397073780000;

And just to ensure we've used a properly formatted string for parsing the date:

var date = new Date(1397073780000);
// date = Wed Apr 09 2014 16:03:00 GMT-0400 (EDT)

If the original string was invalid then Date.parse would return NaN, so you can simply test with isNaN().

tenub
  • 3,240
  • 1
  • 14
  • 25
0

Checking the semantics using regular expressions will most certainly not work and if it does, it will definitely be the code maintainers' hell.

Your datetime contains the day of the month and the year. this means you have to take account of the leap year condition to correctly account for 29th February. Therefore you should reconsider whether you really need and want to use regex to do the job as the patterns will become very complicated and close to unmaintainable.

if you really want to employ, you may try the following one as a start (which ignores 29th February):

var militaryDateTime =
    /^\s*(
         ((0[1-9]|1[0-9]|2[0-8])([01][0-9]|2[0-3])[0-5][0-9][zZ]\s+Feb                          \s+[0-9]{2})
        |((0[1-9]|2[0-9]|30)    ([01][0-9]|2[0-3])[0-5][0-9][zZ]\s+(Apr|Jun|Sep|Nov)            \s+[0-9]{2})
        |((0[1-9]|2[0-9]|3[01]) ([01][0-9]|2[0-3])[0-5][0-9][zZ]\s+(Jan|Mar|May|Jul|Aug|Oct|Dec)\s+[0-9]{2})
     )\s*$/;

Of course you'd have to wrap this into a single line and delete the spaces as js regex does not support human-readable lexicalizations of regular expressions.

Notice:
Did you know that SO has sort of a portal page for the most common regex-related questions? The regex FAQ/Reference/WiKi page.

Community
  • 1
  • 1
collapsar
  • 15,446
  • 3
  • 28
  • 56