HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Formatting a date range, with shortening if the interval falls entirely within a calendar month

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
formattingentirelytheshorteningwithrangeintervaldatewithinmonth

Problem

The graphic guy wants to display dates like

  • 16. February



  • 17. - 24. February, or



  • 25. February - 02. March.



Here is my solution:

$d1 = new \DateTime('2015-02-06');
$d2 = new \DateTime('2015-03-02');

$dateDiff = $d1->diff($d2);
if (intval($dateDiff->d) != 0) {
    $d = $d1->format('d.') . ' ' . ($d1->format('m') != $d2->format('m') ? $d1->format('F') : '') . ' - ' . $d2->format('d. F');
} else {
    $d = $d1->format('d. F');
}


I'm wondering if the this comparison:

$d1->format('m') != $d2->format('m')


is the best way to check whether $d1 and $d2 are in the same or different months.

($dateDiff = $d1->diff($d2) tells me that the two dates are 24 days apart, but it doesn't tell me if they are in different calendar months.)

Solution

This is a self-contained problem, with well-defined inputs and outputs. To be maintainable, the code should reside in a function.

You have three distinct cases, and maybe more:

  • Start and end dates are the same day



  • Start and end dates fall in the same calendar month



  • Start and end dates span calendar months



Your solution should therefore be written to make it obvious that there are more than two cases.

Bugs in your implementation

intval($dateDiff->d) != 0 is an invalid check. You would be treating the range from 2015-01-22 to 2015-03-22 as if it were one day.

Similarly, $d1->format('m') != $d2->format('m') is not quite right either. It would be deceptive to format the range from 2014-12-26 to 2015-12-25 as 26. – 25. December. It might be acceptable to say 26. December – 25. December. But really, it would be clearest to include the years as well.

Suggested solution

function formatDateRange($d1, $d2) {
    if ($d1->format('Y-m-d') === $d2->format('Y-m-d')) {
        # Same day
        return $d1->format('d. F');
    } elseif ($d1->format('Y-m') === $d2->format('Y-m')) {
        # Same calendar month
        return $d1->format('d.') . $d2->format(' – d. F');
    } elseif ($d1->format('Y') === $d2->format('Y')) {
        # Same calendar year
        return $d1->format('d. F') . $d2->format(' – d. F');
    } else {
        # General case (spans calendar years)
        return $d1->format('d. F Y') . $d2->format(' – d. F Y');
    }
}

Code Snippets

function formatDateRange($d1, $d2) {
    if ($d1->format('Y-m-d') === $d2->format('Y-m-d')) {
        # Same day
        return $d1->format('d. F');
    } elseif ($d1->format('Y-m') === $d2->format('Y-m')) {
        # Same calendar month
        return $d1->format('d.') . $d2->format(' – d. F');
    } elseif ($d1->format('Y') === $d2->format('Y')) {
        # Same calendar year
        return $d1->format('d. F') . $d2->format(' – d. F');
    } else {
        # General case (spans calendar years)
        return $d1->format('d. F Y') . $d2->format(' – d. F Y');
    }
}

Context

StackExchange Code Review Q#78295, answer score: 6

Revisions (0)

No revisions yet.