Help with a regular expression in php
I'm trying to get the following regex pattern to work for the following conditions. Allowed values are years 1978 or 1978-1979 for 20th and 21st c开发者_JAVA百科entury, so also 2010-2011. Also if it's 2 years like 1978-1979, they can only be one year apart.
I have gotten up to the following which is accepting 4 digits /^[1-9]{4}$/ which is pretty basic. But any help would be greatly appreciated!
You can ensure that each of the years are from 1900 to 2099 using the regex, but you need to use program logic to validate that the second (optional) year is greater than the first. Here is a tested function (with a commented regex) to validate the year (or year range):
function validYear($yearfield) {
if (preg_match('/
# Match a 20th or 21st century year (or range of years).
^ # Anchor to start of string.
( # $1: Required year.
(?:19|20) # Century is 19 or 20.
[0-9]{2} # Year is 00 to 99.
) # End $1: start year.
(?: # Group for optional range part.
- # Range part requires - separator.
( # $2: Range ending year.
(?:19|20) # Century is 19 or 20.
[0-9]{2} # Year is 00 to 99.
) # End $2: Range ending year.
)? # Range part is optional.
$ # Anchor to end of string.
/x', $yearfield, $matches))
{
$year1 = (int)$matches[1];
$year2 = isset($matches[2]) ? (int)$matches[2] : $year1 + 1;
if ($year2 > $year1) return true;
}
return false;
}
The only way to do this is in 2 steps. First, you'll need to use a regular expression to extract the 2 dates and then you'll need to validate that if there are 2 dates, that they're 1 year apart.
Solution:
<?php
preg_match('/^((?:19|20)\d{2})(?:-((?:19|20)\d{2}))$/', '1898-1899', $matches);
// Validate a date range
if ( ! empty($matches[2]) && intval($matches[2]) - intval($matches[1]) != 1 )
die('Invalid date range');
if ( empty($matches[1]) )
die('Invalid date');
I don't think this is really the best use for regex, but I like a challenge.
So just to show that anything is possible in regex http://regexr.com?2u843:
^(?=[0-9]{4}$|1999-2000|([0-9]{2})[0-8]9-\1[1-9]0|([0-9]{3})[0-8]-\2[1-9])(?:19|20)(?=[^-]*$|([0-9]).*\3.$|09.*10$|19.*20$|29.*30$|39.*40$|49.*50$|59.*60$|69.*70$|79.*80$|89.*90$|99.*00$)[0-9](?=[^-]*$|0.*1$|1.*2$|2.*3$|3.*4$|4.*5$|5.*6$|6.*7$|7.*8$|8.*9$|9.*0$)[0-9](?:-[0-9]{4})?$
Explanation:
^ # The start of the string
# This piece prevents 1979-1991 and 1989-2000
(?=
[0-9]{4}$| #either 4 digits
1999-2000| #or 1999-2000
([0-9]{2})[0-8]9-\1[1-9]0| #or first two digits are the same and last digit is 9-0
([0-9]{3})[0-8]-\2[1-9] #or first three digits are the same
)
#now begins the matching
(?:19|20) #Match a 19 or a 20
#This look ahead constricts the to either 4 digits, or to valid transistions for the 3rd digit.
(?=
[^-]*$| #No dash
([0-9]).*\3.$| #Or the same digit
#Or one digit apart.
09.*10$|19.*20$|29.*30$|39.*40$|49.*50$|59.*60$|69.*70$|79.*80$|89.*90$|99.*00$
)
[0-9] #the third digit.
#This look ahead constricts the to either 4 digits, or to valid transistions for the 3rd digit.
(?=
[^-]*$| #No dash
#Or one digit apart.
0.*1$|1.*2$|2.*3$|3.*4$|4.*5$|5.*6$|6.*7$|7.*8$|8.*9$|9.*0$
)
[0-9] #the 4th digit
(?:-[0-9]{4})? #the optional second year.
$ #the end of the string.
This is the regex I came up with:
preg_match('/^(((?:19|20)[0-9]{2})(?:-((?:19|20)[0-9]{2}))?)$/', $string)
It will match either (valid) single years, or double years.
Capturing group 1 contains the fully matched content (be it 2011 or 2011-2012), group 2 matches the first year, and group 3 matches the second year (if found)
For the double years: use php to check wether or not they are 1 year apart
精彩评论