1
\$\begingroup\$

I've written a function to take the difference between two dates and display it in a particular format. I've used a lot of if-else statements, which seems a little messy. Is there a way to shorten this up? Would using the ternary operator make sense?

$date1 = '2018-04-30 10:36:29';
$date2 = '2018-04-30 10:35:29';

echo dateDiff($date1, $date2);

function dateDiff($date1, $date2)
{
    $date_1 = new DateTime($date1);
    $date_2 = new DateTime($date2);

    $diff = $date_1->diff($date_2);

    if($diff->days > 365){
      return $date_1->format('Y-m-d');
    }

    elseif($diff->days < 366 AND $diff->days > 7){
      return $date_1->format('M d');
    }

    elseif($diff->days > 2 AND $diff->days < 8){
      return $date_1->format('L - H:i');
    }

    elseif($diff->days == 2) return "Yesterday ".$date_1->format('H:i');

    elseif($diff->days < 2 AND $diff->days > 0 OR $diff->days == 0 AND $diff->h > 1) return $date_1->format('H:i');

    elseif($diff->days == 0 AND $diff->h < 1 AND $diff->i >= 1) return $diff->i." min ago";

    elseif($diff->days == 0 AND $diff->h < 1 AND $diff->i < 1) return "just now";

    else return $error = "Error!";

}
\$\endgroup\$
3
  • \$\begingroup\$ return $error = "Error!"; why? \$\endgroup\$
    – hjpotter92
    Commented Jan 12, 2018 at 17:40
  • \$\begingroup\$ Just wrote to test the code only. @hjpotter92 \$\endgroup\$ Commented Jan 12, 2018 at 17:43
  • \$\begingroup\$ Many online sites (including this one) use the exact same feature you are trying to code. So it may prove useful to read their source code to see how they do it. This will certainly give you new ideas and you will be free to implement the one you like best. \$\endgroup\$ Commented Jan 12, 2018 at 17:48

2 Answers 2

1
\$\begingroup\$

Chained ternary expressions in PHP are a major pain in the ass — don't use them!

You have a lot of tests that are redundant, since earlier tests will have already eliminated longer periods. The error case at the end also seems pointless.

Use consistent indentation and braces for readability and safety — please don't skimp.

function dateDiff($date1, $date2)
{
    $date_1 = new DateTime($date1);
    $date_2 = new DateTime($date2);
    $diff = $date_1->diff($date_2);

    if ($diff->days > 365) {
        return $date_1->format('Y-m-d');
    } elseif ($diff->days > 7) {
        return $date_1->format('M d');
    } elseif ($diff->days > 2) {
        return $date_1->format('L - H:i');
    } elseif ($diff->days == 2) {
        return "Yesterday ".$date_1->format('H:i');
    } elseif ($diff->days > 0 OR $diff->h > 1) {
        return $date_1->format('H:i');
    } elseif ($diff->i >= 1) {
        return $diff->i." min ago";
    } else {
        return "Just now";
    }
}

Be sure to use consistent capitalization for "yesterday" and "just now".

\$\endgroup\$
0
\$\begingroup\$

Here's a modifying version of @200_success's answer which is intended for comparing a UNIX timestamp in the past with the current time. It provides a human readable result which is correct for a particular timezone and has various special human phrasings for recent timestamps.

// Returns a date/time formatted with human friendly phrasing for recent dates
function formatRecentDate($ts, $timezone) {
    $tz = new DateTimeZone($timezone);
    $date = (new DateTime('now', $tz))->setTimestamp($ts);
    $now = new DateTime('now', $tz);
    $diff = $date->diff($now);
        
    if ($diff->d <= 5) {
        // Less than 5 days ago
        if ($date->format('w') == $now->format('w')-1 || ($date->format('w') == 6 && $now->format('w') == 0)) {
            // Some time yesterday
            return 'Yesterday at '.$date->format('g:ia');
        } else if ($diff->d >= 1) {
            // 2-5 days ago but not within yesterday
            return $date->format('l \a\t g:ia');
        } else if ($diff->h > 1) {
            // 2-23 hours ago within the same date
            return $diff->h." hours ago";
        } else if ($diff->h == 1) {
            // 1 hour ago
            return "an hour ago";
        } else if ($diff->i > 1) {
            // 2-59 minutes ago
            return $diff->i." minutes ago";
        } else if ($diff->i == 1) {
            // 1 minute ago
            return "a minute ago";
        } else if ($diff->s > 1) {
            // 2-59 seconds ago
            return $diff->s." seconds ago";
        } else {
            // 1 second ago
            return "a second ago";
        }
    } else if ($date->format('Y') != $now->format('Y')) {
        // Not in the same year
        return $date->format('jS F Y');
    } else {
        // More than 5 days ago within the same year
        return $date->format('jS F \a\t g:ia');
    }
}
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Welcome to Code Review! You have presented an alternative solution, but haven't reviewed the code. Please edit to show what aspects of the question code prompted you to write this version, and in what ways it's an improvement over the original. It may be worth (re-)reading How to Answer. \$\endgroup\$ Commented Nov 16, 2022 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.