Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify a 4 digit number inside of a string and inserting colon

I have a string and i want to modify all 4 digit numbers and inserting colon between. Example: 1320 will become 13:20

$data = "The time is 1020 and the time is 1340 and 1550";

I'm thinking to use preg_match('/[0-9]{4}/', '????', $data);

But not sure how to pass the same value again in the preg?

like image 390
Khalil Ghanem Avatar asked Apr 06 '19 12:04

Khalil Ghanem


2 Answers

One way could be to use preg_replace instead and use capturing groups to capture 2 times 2 digits (\d{2})(\d{2}) between word boundaries \b

In the replacement use the 2 capturing groups using $1:$2

$data = "The time is 1020 and the time is 1340 and 1550";
$data = preg_replace('/\b(\d{2})(\d{2})\b/', "$1:$2", $data);
echo $data;

Result:

The time is 10:20 and the time is 13:40 and 15:50

Php demo

like image 66
The fourth bird Avatar answered Nov 02 '22 12:11

The fourth bird


You don't need to use capture groups, you merely need to seek the qualifying 4-digit substrings and target the zero-length position in the middle of the substring.

Code: (Demo)

$data = "The time is 1020 and the time is 1340 and 1550";    
echo preg_replace('~\b\d{2}\K(?=\d{2}\b)~', ':', $data);

Output:

The time is 10:20 and the time is 13:40 and 15:50

\b is a word boundary which ensures you're match the first digit in the sequence
\d{2} matches the first two digits
\K "restarts the full string match" -- effectively forgets the previous two digits
(?=\d{2}\b) is a lookahead for two digits not followed by a digit.

preg_replace() replaces the zero-length position with the colon.


If you wanted to improve the validation with this replacement, you could specify some known character ranges like this:

echo preg_replace('~\b[0-2]\d\K(?=[0-5]\d\b)~', ':', $data);

Of course the above isn't 100% reliable because it would match times like 2900. Validating everything between 0000 and 2400 gets considerably hairier:

echo preg_replace('~\b(?:(?:(?:[01]\d|2[0-3])\K(?=[0-5]\d\b))|(?:24\K(?=00\b)))~', ':', $data);

*note, I don't like the inclusion of 2400, but I have read arguments claiming that it is a valid time. This is why I am including it.

If you want to omit 2400 as a valid value, then it is a bit more manageable (0000 - 2359):

echo preg_replace('~\b(?:[01]\d|2[0-3])\K(?=[0-5]\d\b)~', ':', $data);
like image 36
mickmackusa Avatar answered Nov 02 '22 14:11

mickmackusa