Home > Software engineering >  Parse date range expression where end month is omitted when it is the same as the start month
Parse date range expression where end month is omitted when it is the same as the start month

Time:08-15

I have a date field that looks like the following:

$exampleOne = 'Sep 04-08';
$exampleTwo = 'Sep 29-Oct 01';

How can I separate them to become:

$exampleOneResult = {'Sep 04', 'Sep 08'};
$exampleTwoResult = {'Sep 29', 'Oct 01'};

I was thinking to make a loop of splitting '-' first, then splitting ' ' second, but I think that would be too resource heavy?

CodePudding user response:

Split at the dash for from and to. And then check for the second value and supply if missing.

Doing such logic is not resource heavy. Why using a regex for such a simple thing?

This example is for PHP8

$exampleOne = 'Sep 04-08';
$exampleTwo = 'Sep 29-Oct 01';

print_r(parseDateRange($exampleOne));
print_r(parseDateRange($exampleTwo));

function parseDateRange($dateRange): array {
    [$from, $to] = explode('-', $dateRange);
    [$month] = explode(' ', $from);
    if(!str_contains($to, ' ')) {
        $to = "$month $to";
    }

    return [$from, $to];
}

prints

Array
(
    [0] => Sep 04
    [1] => Sep 08
)
Array
(
    [0] => Sep 29
    [1] => Oct 01
)

CodePudding user response:

For a concise and direct approach with fewer temporary variables, pre-hydrate the string to contain two months, then unconditionally explode on the hyphen. Done.

Pattern:

^         #from start of the string
(\D{4})   #capture four non-digit characters
\d{2}     #match two digit characters
-         #match  hyphen
\K        #forget/release all matched characters
(?=\d)    #check that the next character is a digit (the month is missing)

The $1 in the replacement injects the month and space from the front of the string into the position immediately after the hyphen without consuming any characters in the process.

Code: (Demo)

$examples = [
    'Sep 04-08',
    'Sep 29-Oct 01',
];

$result = [];
foreach ($examples as $example) {
    var_export(
        explode('-', preg_replace('/^(\D{4})\d{2}-\K(?=\d)/', '$1', $example))
    );
    echo "\n";
}

Output:

array (
  0 => 'Sep 04',
  1 => 'Sep 08',
)
array (
  0 => 'Sep 29',
  1 => 'Oct 01',
)

Or you can achieve the same result without regex by "left padding" the "to" string with the "from" string because the "from" string will always have all 6 characters and the "to" string will never have less than 2 characters. In other words, the days from the "from" string will ALWAYS be overwritten by the "to" days. Demo

$result = [];
foreach ($examples as $example) {
    [$from, $to] = explode('-', $example, 2);
    var_export([$from, str_pad($to, 6, $from, STR_PAD_LEFT)]);
    echo "\n";
}
  • Related