-3

How to return the two date combine string like below.

Start Date : 11/2/2020
End Date : 26/2/2020

Then Output should be like this : 11 to 26 feb 2020

Start Date : 26/2/2020
End Date : 5/3/2020

Then Output should be like this : 26 feb to 5 march 2020

Start Date : 29/12/2020
End Date : 2/1/2021

Then Output should be like this : 29 Dec 2020 to 2 Jan 2021

Please Help me to solve this issue.

CBroe
  • 91,630
  • 14
  • 92
  • 150
AKM
  • 25
  • 5
  • 3
    Welcome to Stack Overflow. This is a nice problem. What have you tried so far? – KIKO Software Feb 20 '20 at 09:04
  • @KIKOSoftware Sorry, I can not thinking this type of logic. – AKM Feb 20 '20 at 09:12
  • 2
    You need to start by looking at all three components of the date separately - day, month, and year. If the year is the same, then you will only have to output it once - otherwise, each output value needs to be the complete date. If the year is the same, then perform the same check on the month, and output the appropriate parts. – CBroe Feb 20 '20 at 09:18
  • Here is your answer : https://stackoverflow.com/a/60039218/12232340 if you are english then use first solution in answer, if not english then use second solution. –  Feb 20 '20 at 09:22

2 Answers2

0

Welcome to stackoverflow :-)

PHP has a native DateTime class which allows you to perform date manipulations and date-formatting.

In your specific case you could start to convert your two dates into objects and then reformat it into your expected format.

Here is an example:

$date = DateTime::createFromFormat('d/m/Y', $startString);

With this in mind we can now create a function which will check your requirements and return the string on your custom format.

function my_date_range(DateTime $start, DateTime $end)
{
    $sameYear = $start->format('Y') === $end->format('Y');
    $sameMonth = $sameYear && $start->format('m') === $end->format('m');
    $sameDay = $sameMonth && $start->format('d') === $end->format('d');

    if ($sameDay) {
        return $start->format('d M Y');
    }
    if ($sameMonth) {
        return sprintf('%s to %s', $start->format('d'), $end->format('d M Y'));
    }
    if ($sameYear) {
        return sprintf('%s to %s', $start->format('d M'), $end->format('d M Y'));
    }

    return sprintf("%s to %s", $start->format('d M Y'), $end->format('d M Y'));
}

Below you'll find my example dates and usage:

var_dump(
    my_date_range(DateTime::createFromFormat('d/m/Y', '11/2/2020'), DateTime::createFromFormat('d/m/Y', '26/2/2020')),
    my_date_range(DateTime::createFromFormat('d/m/Y', '26/2/2020'), DateTime::createFromFormat('d/m/Y', '5/3/2020')),
    my_date_range(DateTime::createFromFormat('d/m/Y', '29/12/2020'), DateTime::createFromFormat('d/m/Y', '2/1/2021')),
    my_date_range(DateTime::createFromFormat('d/m/Y', '2/1/2021'), DateTime::createFromFormat('d/m/Y', '2/1/2021')),
)

Result:

string(17) "11 to 26 Feb 2020"
string(21) "26 Feb to 05 Mar 2020"
string(26) "29 Dec 2020 to 02 Jan 2021"
string(11) "02 Jan 2021"
Christoph Kluge
  • 1,947
  • 8
  • 23
  • 1
    That does not take part of leaving out the “repeating” parts that are the same for both dates. You would just get `11 feb 2020 to 26 feb 2020` for the first example here, and that is not what was asked for. – CBroe Feb 20 '20 at 09:38
  • @CBroe oh wow. Thank you for the hint. You are totally right. I will adopt my answer :-) – Christoph Kluge Feb 20 '20 at 09:54
0

One way to do this:

  • put your date parts into arrays - ['11', 'Feb', '2020']

  • loop over them in reverse order, from year to day

  • unset each entry in your start date array, that has the same value as the corresponding entry in your end date array - for as long as the current part matches; break out of the loop once the first mismatch occurs

  • join the parts that are left back together

 

function time_range_format($start, $end) {
  for($i=2; $i>=0; --$i) {
    if($end[$i] == $start[$i]) {
      unset($start[$i]);
    }
    else {
      break; // important to leave the loop, once the first non-matching part is encountered
    }
  }
  return ($start ? implode(' ', $start) . ' to ' : '') . implode(' ', $end);
}

var_dump(
  time_range_format(['11', 'Feb', '2020'], ['26', 'Feb', '2020']),
  time_range_format(['26', 'Feb', '2020'], ['5', 'Mar', '2020']),
  time_range_format(['29', 'Dec', '2020'], ['2', 'Jan', '2021']),
  time_range_format(['29', 'Dec', '2020'], ['29', 'Dec', '2020'])
);

Results for above examples:

11 to 26 Feb 2020
26 Feb to 5 Mar 2020
29 Dec 2020 to 2 Jan 2021
29 Dec 2020

By checking if $start still contains anything at the end, and only putting out the to if it does, you can even handle the “edge case” that start and end date are the same, as in the very last row of this example.

CBroe
  • 91,630
  • 14
  • 92
  • 150