Regular Expression for date validation - Explain - javascript

I was surfing online for date validation, but didn't exactly understand the regex. Can anyone explain it? I'm confused with ?, {} and $. Why do we need them?
dateReg = /^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$/;

? means “zero or one occurences”.
{x} (where x is a number) means “exactly x occurences”
$ means “end of line”
These are very basic regex, I recommand you to read some documentation.

^ = beginning of the string
[0,1]? = optional zero, one or comma (the comma is probably an error)
\d{1} = exactly one digit (the {1} is redundant)
\/ = a forward slash
[0-2]? = optional zero, one or two (range character class) followed by any single digit (\d{1})
OR [3] = three (character class redundant here) followed by exactly one zero, one or comma
\/ = forward slash
[1]{1}[9]{1}[9]{1}\d{1} = 199 followed by any digit
OR 2-9 followed by any 3 digits
Overall, that's a really poorly written expression. I'd suggest finding a better one, or using a real date parser.

In Javascript you could validate date by passing it to Date.Parse() function. Successful conversion to a date object means you have a valid date.
Wouldn't recommend using regex for this. Too many edge cases and code gets hard to maintain.

? means "Zero or one of the aforementioned"
{n} means "exactly n of the aforementioned"
$ is the end of the String (Thanks #Andy E)

To summarize briefly:
`?' will match 0 or 1 times the pattern group you put in front of it. In this case, it's possibly being misused and should be left out, but it all depends on just what you want to match.
`{x}' tells the regex to match the preceding pattern group exactly x times.
`$' means to match the end of the line.

Well:
^ // start of the text
$ // end of the text
X{n} // number n inside these curly parenthesis define how many exact occurrences of X
X{m,n} // between m to n occurrences of X
X? // 0 or 1 occurrence of X
\d // any digits 0-9
For more help about Javascript date validation please see: Regular Expression to only grab date

Related

Regex exact match on number, not digit

I have a scenario where I need to find and replace a number in a large string using javascript. Let's say I have the number 2 and I want to replace it with 3 - it sounds pretty straight forward until I get occurrences like 22, 32, etc.
The string may look like this:
"note[2] 2 2_ someothertext_2 note[32] 2finally_2222 but how about mymomsays2."
I want turn turn it into this:
"note[3] 3 3_ someothertext_3 note[32] 3finally_2222 but how about mymomsays3."
Obviously this means .replace('2','3') is out of the picture so I went to regex. I find it easy to get an exact match when I am dealing with string start to end ie: /^2$/g. But that is not what I have. I tried grouping, digit only, wildcards, etc and I can't get this to match correctly.
Any help on how to exactly match a number (where 0 <= number <= 500 is possible, but no constraints needed in regex for range) would be greatly appreciated.
The task is to find (and replace) "single" digit 2, not embedded in
a number composed of multiple digits.
In regex terms, this can be expressed as:
Match digit 2.
Previous char (if any) can not be a digit.
Next char (if any) can not be a digit.
The regex for the first condition is straightforward - just 2.
In other flavours of regex, e.g. PCRE, to forbid the previous
char you could use negative lookbehind, but unfortunately Javascript
regex does not support it.
So, to circumvent this, we must:
Put a capturing group matching either start of text or something
other than a digit: (^|\D).
Then put regex matching just 2: 2.
The last condition, fortunately, can be expressed as negative lookahead,
because even Javascript regex support it: (?!\d).
So the whole regex is:
(^|\D)2(?!\d)
Having found such a match, you have to replace it with the content
of the first capturing group and 3 (the replacement digit).
You can use negative look-ahead:
(\D|^)2(?!\d)
Replace with: ${1}3
If look behind is supported:
(?<!\d)2(?!\d)
Replace with: 3
See regex in use here
(\D|\b)2(?!\d)
(\D|\b) Capture either a non-digit character or a position that matches a word boundary
(?!\d) Negative lookahead ensuring what follows is not a digit
Alternations:
(^|\D)2(?!\d) # Thanks to #Wiktor in the comments below
(?<!\d)2(?!\d) # At the time of writing works in Chrome 62+
const regex = /(\D|\b)2(?!\d)/g
const str = `note[2] 2 2_ someothertext_2 note[32] 2finally_2222 but how about mymomsays2.`
const subst = "$13"
console.log(str.replace(regex, subst))

Confusing with Regular Expressions repeaing parts

I am really confused with Regular Expressions repeating parts with curly braces. Consider the following example:
var dateTime = /\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}/;
console.log(dateTime.test("30/1/2003 8:45"));
// true
Now if I change 30 to 300000 and 45 to 455555, I'll get true again! Other parts between outer numbers are ok and the result is as expected.
Can somebody help me find the problem?
Thanks.
You're not matching the beginning and end of the String (^ and $) so it's just finding a match anywhere in the String which still happens, and then giving true.
300000/1/2003 8:455555
dd/m/yyyy h:mm
You probably want
/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/;
Or to be even more exact;
/^(?:0?[1-9]|[12]\d|3[01])\/(?:0?[1-9]|1[0-2])\/\d{4} (?:0?\d|1\d|2[0-3]):[0-5]\d$/;
(?:pattern) non capture group
pattern? the n in pattern is optional
[1-9] character class; a number ranging from 1 to 9
pattern1|pattern2 either pattern1 or pattern2
[12] character class; either 1 or 2
\d same as [0-9]
pattern{4} the n in pattern happens 4 times
You're not matching the whole string, just part of it - using the test function, that's enough to return True.
Try this instead:
/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/
The ^ anchor matches the beginning of the string, the $ one matches the end of the string.
You can find more useful information about a match by using string.match(regex) rather than regex.test(string).
In this case, you'd see that it's matching 00/1/2003 8:45 because you did not use ^ and $ to mark the start and end of the subject string, respectively.
What is happening is that when you change 30 to 30000, the last two zeroes(00) of 30000 are matched and with 45555 the matching is stopped with first two digits(45) and the rest of the string is not matched.
To stop that from happening, you have to indicate that the string must begin and end with regex specified.
This can be done using anchors. Like this -
var dateTime = /^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/;
^ ^

jQuery/JavaScript regex to match any three first characters followed by an exact string

I need a regular expression to validate a form, based on the value of a drop down. The value, however, is randomly generated by PHP (but is always a 2 digit number).
It needs to be valid for "38|One Evening" The number 38 is what's going to change. So far, I have
//return value of dropdown
var priceOption = $("#price_option-4").val();
//make sure it ends with "One Evening"
var oneEvening = priceOption.match(/^ * + 'One Evening' $/);
Which I thought would match any string as long as it's followed by "one evening"
strings are not to be use with regex, you should just write what you want to match\test inside the regex literal, without the quotes.
/^\d{2}\|One Evening$/.test(priceOption);
// ^^^^^^ Begins with two digits
// ^^ Escaped the | meta char.
// ^^^^^^^^^^^^ Then until the end: One Evening
Simply use
/^\d\d\|One Evening$/.test(priceOption);
For xx|One Evening
/^\d{2}\|One Evening$/
/^.+?One Evening$/
Breaking it down
// ^ starts with
// . any character
// + quantifier - one or more of preceding character
// ? non-greedy - ensure regex stops at One Evening.
// One Evening = literal text
// $ match end of string.
Note that my answer reflects the requirement to match any sequence of characters, then One Evening.
I think you may be better off being more specific and ensuring you definitely have two numeric characters.
If you can it is best to be specific. Try the following:
// <start of string> <2 digits> <|One Evening> <end of string>
/^\d{2}\|One Evening$/.test( priceOption );

JavaScript RegExp to match a (partial) hour

I want to allow people to enter times into a textbox in various formats. One of the formats would be either:
2h for 2 hours, or
2.5h for 2 and a half hours
I want to use a regex to recognise the pattern but it's not picking it up for some reason:
I have:
var hourRegex = /^\d{1,2}[\.\d+]?[h|H]$/;
which works for 2h, but not for 2.5h.
I thought that this regex would mean - Start at the beginning of the string, have one or two digits, then have none or one decimal points which if present must be followed by one or more digits then have a h or a H and then it must be the end of the string.
I have tried the regex tool here but no luck.
/^\d{1,2}(?:\.\d+)?h$/i; Use parentheses instead of square braces.
Start at the beginning
One or two digits
Optional: a dot followed by at least one digit
End with a h
Case insensitive
RegExp tuturial
[...] - square braces mean: anything which is within the provided range.
[^...] means: Match a character which is not within the provided range
(...) - parentheses mean: Group me. Optionally, the first characters of a group can start with:
?: - Don't reference me (me, I = group)
?= - Don't include me in the match, though I have to be here
?! - I may not show up at this point
{a,b}, {a,} means: At least a, maximum b characters. Omitting b = Infinity
+ means: at least one time, match as much as possible equivalen to {1,}
* means: match as much as possible equivalent to {0,}
+? and *? have the same effect as previously described, with one difference: Match as less as possible
Examples
[a-z] One character, any character between a, b, c, ..., z
(a-z) Match "a-z", and group it
[^0-9] Match any non-number character
See also
MDN: Regular Expressions - A more detailed guide
The trouble is here :
[\.\d+]
you can not use character classes inside brackets.
Use this instead:
(\.[0-9]+)?
You've confused your square brackets with your parenthesis. Square brackets look for a single match of any contained character, whereas parenthesis look for a match of the entire enclosed pattern.
Your issue lies in [\.\d+]? It's looking for . or 0-9 or +.
Instead you should try:
/^\d{1,2}(\.\d+)?(h|H)$/
Although that will still allow users to enter invalid numbers, such as 99.3 which is probably not the expected behavior.

JavaScript and regular expressions: get the number of parenthesized subpattern

I have to get the number of parenthesized substring matches in a regular expression:
var reg=/([A-Z]+?)(?:[a-z]*)(?:\([1-3]|[7-9]\))*([1-9]+)/g,
nbr=0;
//Some code
alert(nbr); //2
In the above example, the total is 2: only the first and the last couple of parentheses will create grouping matches.
How to know this number for any regular expressions?
My first idea was to check the value of RegExp.$1 to RegExp.$9, but even if there are no corresponding parenthseses, these values are not null, but empty string...
I've also seen the RegExp.lastMatch property, but this one represents only the value of the last matched characters, not the corresponding number.
So, I've tried to build another regular expression to scan any RegExp and count this number, but it's quite difficult...
Do you have a better solution to do that?
Thanks in advance!
Javascripts RegExp.match() method returns an Array of matches. You might just want to check the length of that result array.
var mystr = "Hello 42 world. This 11 is a string 105 with some 2 numbers 55";
var res = mystr.match(/\d+/g);
console.log( res.length );
Well, judging from the code snippet we can assume that the input pattern is always a valid regular expression, because otherwise it would fail before the some code partm right? That makes the task much easier!
Because We just need to count how many starting capturing parentheses there are!
var reg = /([A-Z]+?)(?:[a-z]*)(?:\([1-3]|[7-9]\))*([1-9]+)/g;
var nbr = (' '+reg.source).match(/[^\\](\\\\)*(?=\([^?])/g);
nbr = nbr ? nbr.length : 0;
alert(nbr); // 2
And here is a breakdown:
[^\\] Make sure we don't start the match with an escaping slash.
(\\\\)* And we can have any number of escaped slash before the starting parenthes.
(?= Look ahead. More on this later.
\( The starting parenthes we are looking for.
[^?] Make sure it is not followed by a question mark - which means it is capturing.
) End of look ahead
Why match with look ahead? To check that the parenthes is not an escaped entity, we need to capture what goes before it. No big deal here. We know JS doens't have look behind.
Problem is, if there are two starting parentheses sticking together, then once we capture the first parenthes the second parenthes would have nothing to back it up - its back has already been captured!
So to make sure a parenthes can be the starting base of the next one, we need to exclude it from the match.
And the space added to the source? It is there to be the back of the first character, in case it is a starting parenthes.

Categories

Resources