Home > Enterprise >  How to write a regular expression that contains the day and month?
How to write a regular expression that contains the day and month?

Time:01-29

I need to write a regular expression for my .htacces file that matches the following:

gallery/a-day-like-today
gallery/a-day-like-today/
gallery/a-day-like-today/2-18
gallery/a-day-like-today/2-18/

Basically, the numbers (2-18) represents the month and the day. It could also contain 1 digit like 9-8 (september the 8th)

If there is a date, then both the month and the day are mandatory.

I started doing something but i'm stock. Any ideas how to achieve it?

^gallery/a-day-like-today(?:/(\d{1,12})-(\d{1,31})?)?$

My solution doesn't work because it picks days that are out of the range {1,31}

my htacces looks like this:

RewriteRule ^gallery/a-day-like-today(?:/(\d{1,12})-(\d{1,31})?)?$ gallery/a_day_like_today.php?month=$1&day=$2 [L]

https://regex101.com/r/zkBQSJ/1

CodePudding user response:

From (\d{1,12}) I can tell that you try to do a range check for month 1...12. Your regex actually means a number 1 to 12 digits long. You can do a range check in regex, but it's a bit convoluted, meaning you might want to extract the numbers, and do the range check on the extracted numbers.

Here is a regex solution for your range check for month and day:

const regex = /^gallery\/a-day-like-today(?:\/?|\/([1-9]|1[0-2])-([1-9]|[12][0-9]|3[01])\/?)$/;
[
  'gallery/a-day-like-today',
  'gallery/a-day-like-today/',
  'gallery/a-day-like-today/2-18',
  'gallery/a-day-like-today/2-18/',
  'gallery/a-day-like-today/12-1/',
  'gallery/a-day-like-today/13-1/',
  'gallery/a-day-like-today/1-31/',
  'gallery/a-day-like-today/1-32/'
].forEach(str => {
  let m = str.match(regex);
  console.log(str, '==>', m);
});

Output:

gallery/a-day-like-today ==> [
  "gallery/a-day-like-today",
  undefined,
  undefined
]
gallery/a-day-like-today/ ==> [
  "gallery/a-day-like-today/",
  undefined,
  undefined
]
gallery/a-day-like-today/2-18 ==> [
  "gallery/a-day-like-today/2-18",
  "2",
  "18"
]
gallery/a-day-like-today/2-18/ ==> [
  "gallery/a-day-like-today/2-18/",
  "2",
  "18"
]
gallery/a-day-like-today/12-1/ ==> [
  "gallery/a-day-like-today/12-1/",
  "12",
  "1"
]
gallery/a-day-like-today/13-1/ ==> null
gallery/a-day-like-today/1-31/ ==> [
  "gallery/a-day-like-today/1-31/",
  "1",
  "31"
]
gallery/a-day-like-today/1-32/ ==> null

Explanation of regex:

  • ^gallery\/a-day-like-today -- literal text at beginning of string
  • (?: -- non-capture group start
    • \/? -- optional slash
  • | -- logical OR
    • \/ -- literal slash
    • (?:[1-9]|1[0-2]) -- capture group 1 for a single digit 1..9, or two digits 10...12
    • - -- literal dash
    • (?:[1-9]|[12][0-9]|3[01]) -- capture group 2 for a single digit 1..9, or two digits 10...29, or 30...31
    • \/? -- optional slash
    • ) -- non-capture group end
  • $ -- end of string

Learn more about regex: https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex

CodePudding user response:

This doesn't check if the numbers make sense as a month day, but it's simple so maybe it will work for your case.

gallery/a-day-like-today/?(\d{1,}-\d{1,})?/?

BTW. Why not just check for gallery/a-day-like-today and not worry about what goes after?

CodePudding user response:

This regex matches all your conditions plus I added more test cases

^gallery/a-day-like-today/{0,1}\d{0,2}-{0,1}\d{0,2}/{0,1}$

https://regex101.com/r/XqcYf6/1


If you want to return the month and day (when present), you can use the regex

^gallery/a-day-like-today/{0,1}(\d{0,2})-{0,1}(\d{0,2})/{0,1}$

https://regex101.com/r/8WYO0t/1


Test cases

gallery/a-day-like-today
gallery/a-day-like-today/
gallery/a-day-like-today/1-1
gallery/a-day-like-today/1-1/
gallery/a-day-like-today/1-31
gallery/a-day-like-today/1-31/
gallery/a-day-like-today/12-1
gallery/a-day-like-today/12-1/
gallery/a-day-like-today/12-31
gallery/a-day-like-today/12-31/

NOTE: This does not check whether the month-day pair are valid, only matches the pattern. For example, /99-99/ would pass but not be a valid month-day pair. You'll have to tell me if this is OK or not.

  • Related