'Pad numbers formatted time expression having variable delimiters with leading zeros

What is the best way to form a string to a specific format like in excel(##,# etc.)?

I want to set the format like 00:00.00, if someone put 1:10.10 i want to add a zero in front of them. If the input looks like 1.5.07 it must convert to 01:50.07, harder one: 0.3 must convert to 00:00.30.

I think this is possible with some regex, i can write the expected format but how can i reform the input with this?

$input = "00:13,40";
echo preg_replace("/(d){2}:(d){2}\.(d){2}/","???",$input);

the , in the input must converted to a dot. The input can be "anything" like 13.40 and must converted to 00:13.40. It must replace wrong separator and add missing 0 in front or end (0:13.4)



Solution 1:[1]

I don't know if I have enough of a test battery from your question details, but the following technique will correct zero-pad the strings that you have provided.

The pattern effectively parses a string with 2 optional sets of numbers, then a required number before the end of the string.

The pattern allows for any combination of colon, comma, or dots as delimiting characters. If you need more delimiting characters, add them to the character classes.

I added a negative lookahead ((?!\d+$)) to ensure that a number with only two sets of numbers does not use the first set as the hours (first number in the result).

sprintf() is an elegant way of enforcing the zero-padded format in each group of the replacement string.

Code: (Demo)

$tests = [
    '1:10.10',
    '1.5.07',
    '0.3',
    '00:13,40',
    '15,17',
];

var_export(
    preg_replace_callback(
        '~(?:(\d{1,2})[:.,](?!\d+$))?(?:(\d{1,2})[:.,])?(\d{1,2})$~',
        function($m) {
            return sprintf('%02d:%02d.%02d', $m[1], $m[2], $m[3]);
        },
        $tests
    )
);

Output:

array (
  0 => '01:10.10',
  1 => '01:05.07',
  2 => '00:00.03',
  3 => '00:13.40',
  4 => '00:15.17',
)

Alternatively, you can achieve the same result by loosening the pattern to match digits and non-digits (in an alternating order) and give priority to values that are farther to the right side of the string.

Code: (Demo)

preg_replace_callback(
    '~(?:(\d+)\D+)??(?:(\d+)\D+)?(\d+)$~',
    function($m) {
        unset($m[0]);
        return vsprintf('%02d:%02d.%02d', $m);
    },
    $tests
)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1