function isValidTime(value) {

var hasMeridian = false;

var re = /^\d{1,2}[:]\d{2}([:]\d{2})?( [aApP][mM]?)?$/;

if (!re.test(value)) { return false; }

if (value.toLowerCase().indexOf("p") != -1) { hasMeridian = true; }

if (value.toLowerCase().indexOf("a") != -1) { hasMeridian = true; }

var values = value.split(":");

if ( (parseFloat(values[0]) < 0) || (parseFloat(values[0]) > 23) ) { return false; }

if (hasMeridian) {

if ( (parseFloat(values[0]) < 1) || (parseFloat(values[0]) > 12) ) { return false; }

}

if ( (parseFloat(values[1]) < 0) || (parseFloat(values[1]) > 59) ) { return false; }

if (values.length > 2) {

if ( (parseFloat(values[2]) < 0) || (parseFloat(values[2]) > 59) ) { return false; }

}

return true;

}

The format of the regular expression needs some explaining. Let's talk about what is allowed. Hours must be present and can be one or two digits. That is \d{1,2} at the start. After that must be a colon. Then the minutes (2 digits) must be present. After that, everything starts to become optional. However, if seconds are present, then there must be a colon and two digits. So the colon and \d{2} is surrounded by parentheses and then followed by a question mark. The question mark says that the whole grouping in parentheses must appear exactly zero or one time. Then we do another grouping that must appear zero or one time. Inside this grouping is a space followed by some characters. The brackets are an indicator that "one of the letters" is correct. So after the space must be an upper or lower case "a" or "p". After that, an upper or lower case "m" can appear (the question mark after the bracket indicates that the "m" must appear zero or one time).

So, that whole regular expression is used to validate the incoming string. Assuming the string is valid, then we can look to see if the individual pieces are in the right ranges. We split the value into an array based on the colon. So, if the incoming string is "12:25" then we'll have two values in our array: "12" and "25". Note that if the incoming string is "12:25 PM", we'll still have two values: "12" and "25 PM".

The first piece must be between 0 and 23. If there is an "a" or "p" in the value, then we set hasMeridian to true and the first piece must be between 1 and 12. The second piece must be between 0 and 59. The third piece, if present, must be between 0 and 59.

Note that we're taking advantage of the way parseFloat works. If the string is "25 PM", parseFloat will see the numbers at the start and then the space and stop evaluating - it will return a value of 25. So we don't have to worry any more about the meridian part being in the value - it will not affect our evaluating of the range of numbers.