Reputation: 3731
I want to have a simple capture and test program for a specific date format (Which is not compatible with Date.parse - NaN) with this RegEx:
/(\d{1,2})\/(\d{1,2})\/(\d{2,4})/ //day/month/year
It works on the rubular tester but using it in chrome yields weird results:
dateRegex.test("19111/7/1992")
> true
"19111/7/1992".match(dateRegex) //Wrong on purpose
> ["11/7/1992", "11", "7", "1992"] //Why is it matching 11?
Is there any specific to JavaScript RegEx that i need to be aware of?
Upvotes: 0
Views: 128
Reputation: 3856
The actual matching routine should be well explained by other answers.
To further validate the date you could do something like this:
function valiDate(d) {
var v, m = d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{1,4})$/);
if (!m)
return false;
v = new Date(m[3], m[2] - 1, m[1]);
return m[1] == v.getDate() &&
m[2] == v.getMonth() + 1 &&
m[3] == v.getFullYear()
;
}
Or the possibly faster:
function valiDate(d) {
function leap(y) {
return !((y%4)||(!(y%100) && (y%400)));
}
var m = d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{1,4})$/);
// Not match || date or month below 1, or month above 12
if (!m || m[1] < 1 || m[2] < 1 || m[2] > 12) {
return false;
// Jan,Mar,May,Jul,Aug,Oct,Dec
} else if ([2,4,6,9,11].indexOf(+m[2]) < 0) {
return m[1] < 32;
// Feb
} else if (m[2] === '2') {
return m[1] < 29 ? true :
m[1] < 30 && leap(+m[3]);
// Apr,Jun,Sep,Nov
} else {
return m[1] < 31;
}
}
Upvotes: 1
Reputation: 13766
Your regex is behaving correctly. Specifically what's happening is the following:
19111/7/1992
^
matching starts at this point, everything before that is ignored
What you need is to specify that your regex should start at the beginning of the string, and end at the end of the string:
/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/
... note the ^
and $
, these will cause any extra characters at the beginning or end to fail the regex.
Upvotes: 0
Reputation: 39443
First of all, this is not the correct way to handle date. It can parse 99/99/9999
as date. I think you are aware about this.
Now come to your question, why it parsed 11/7/1992
? Because you didn't provide any boundary and it matched part of a string. You can do it in several ways.
This forces the entire string to match from end to begin with anchors(^
$
).
/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/
Using \b
to boundary the numbers. This will help you to parse from the middle of any string.
/\b(\d{1,2})\/(\d{1,2})\/(\d{2,4})\b/
Upvotes: 1
Reputation: 288660
Try using
^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$
^
asserts position at the beginning of the string, and $
asserts position at the end of string (or before the line break at the end of the string, if any).
Upvotes: 1