Parse date range expression where end month is omitted when it is the same as the start month

Issue

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?

Solution

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";
}

Answered By – mickmackusa

Answer Checked By – Clifford M. (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.