Home > database >  preg_replace for a time string
preg_replace for a time string

Time:05-25

We are using a preg_replace to get a well formated time string. The result should look like this:

mo-sa9:00-20:00uhr => mo-sa 09:00-20:00uhr

The regex is:

preg_replace('=[^\d](\d{1})[.:](\d{2})=U', ' 0${1}:${2}', $norm)

The result is: mo-s 09:00-20:00uhr

After many attempts, I found that I couldn't seem to find a pattern that correctly formatted the time string.

The replacement seems to be the problem or am I looking at it wrong?

CodePudding user response:

You can use

preg_replace('~(?<!\d)(\d)[.:](\d{2})~', ' $1:$2', $norm)

Or, if you want to keep the separator char:

preg_replace('~(?<!\d)(\d)([.:])(\d{2})~', ' $1$2$3', $norm)

See the regex demo. Details:

  • (?<!\d) - a left-hand digit boundary
  • (\d) - Group 1 ($1): a digit
  • ([.:]) - Group 2 ($2): . or :
  • (\d{2}) - Group 3 ($3): two digits.

See the PHP demo:

<?php

$norm = 'mo-sa9:00-20:00uhr';
echo preg_replace('~(?<!\d)(\d)([.:])(\d{2})~', ' $1$2$3', $norm);
// => mo-sa 9:00-20:00uhr

CodePudding user response:

The current issue is that [^\d] is matching the a but you do nothing with it so it is lost on replacing.

I would use preg_replace_callback and use datetime functions to ensure leading zeros as needed.

echo preg_replace_callback('/(\d\d?:\d\d)-(\d\d?:\d\d)/', function($match){
    return ' ' . date('H:i', strtotime($match[1])) . '-' . date('H:i', strtotime($match[2])); 
}, 'mo-sa9:00-20:00uhr');

https://3v4l.org/K1voc

CodePudding user response:

You can match the part that you want, and assert what should be to the right as well.

Note that you can omit {1}, you can write [^\d] as \D and you don't need the /U flag to make quantifiers lazy.

\D\K(?=\d[.:]\d{2}\b)

Explanation

  • \D Match a non digit and then a single digit
  • \K Forget what is matched so far
  • (?= Positive lookahead to assert what is to the right
    • \d[.:]\d{2} Match a digit, then either . or : and 2 digits
    • \b A word boundary to prevent a partial word match
  • ) Close the lookahead

Regex demo | Php demo

In the replacement use 0

$re = '/\D\K(?=\d[.:]\d{2}\b)/';
$norm = 'mo-sa9:00-20:00uhr';

echo preg_replace($re, " 0", $norm);

Output

mo-sa 09:00-20:00uhr

If the string is always formatted like this, you could also opt for a precise match:

\b[a-z] -[a-z] \K\d:\d\d-\d\d:\d\duhr\b

In the replacement use the 2 capture groups with a space in between.

$re = '/\b[a-z] -[a-z] \K\d:\d\d-\d\d:\d\duhr\b/';
$norm = 'mo-sa9:00-20:00uhr';

echo preg_replace($re, " 0$0", $norm); // mo-sa 09:00-20:00uhr

Regex demo | PHP demo

  • Related