Search code examples
phpregexreplacepreg-replacepreg-replace-callback

Replace based on regex and return manipulated string


I have a logic query as a string, for example:

mydate == 'one day ago' && mydate > 2014-05-16 16:00:00

I need every instance of a date replaced by a timestamp. My current code can replace the YYYY-MM-DD HH:MM:SS date-time to a timestamp using strtotime():

$my_string = "mydate == 'one day ago' && mydate > 2014-05-16 16:00:00";

// Pattern: *YYYY-MM-DD HH:MM:SS*
$pattern = '((?:2|1)\\d{3}(?:-|\\/)(?:(?:0[1-9])|(?:1[0-2]))(?:-|\\/)(?:(?:0[1-9])|(?:[1-2][0-9])|(?:3[0-1]))(?:T|\\s)(?:(?:[0-1][0-9])|(?:2[0-3])):(?:[0-5][0-9]):(?:[0-5][0-9]))';

$my_string = preg_replace_callback($pattern, function($m){return strtotime($m[0]);}, $my_string);

echo($my_string);

Output:

mydate == 'one day ago' && mydate > 1400252400

However, I also want to support natural language relative phrases. The query string is always of a set structure:

mydate OPERATOR 'DATE' && mydate OPERATOR 'DATE'...

What I'd like to do is find the variable mydate skip past the operator then get the contents within the single quotes, apply strtotime() to the contents of the single quotes and then replace the date (including single quotes) with the integer. For example:

Input:

mydate == 'one day ago' && mydate > '2014-05-16 16:00:00'

Target process:

mydate == timetostr('one day ago') && mydate > timetostr('2014-05-16 16:00:00')

Output:

mydate == 123123123123 && mydate > 1400252400

Note the difference between my current and the new input, now I want both instances to have single quotes and not use a regex designed only for date-time strings.

How can I make a regex along the lines of variable_name*'*'

Where * is any character, take the contents of '' and return variable_name*


Solution

  • Try using: [^\-+\*=]+\s*[\-+\*=]{1,2}\s*('[^']+')\s*\&\& (regex101)

    The first character class is any non-operator character 1 or more times, then 0 or more whitespace characters, then 1 or 2 operator characters (you may or may not want to include angle brackets here) then 0 or more whitespace characters then you capture the '*' as you've termed it above.