skip to Main Content

I have this function to give people a little cake icon to celebrate the number of years they’ve been registered, but it seems to give 1 year too short a time?

public function cake_day($reg_date, $username)
{
    $date1 = new DateTime();
    $date1->setTimestamp($reg_date);
    
    $date2 = new DateTime();
    
    $cake_icon = '';
    if ($date1->format('d-m') === $date2->format('d-m')) 
    {
        // calculate how many years
        $total_years = $date1->diff($date2)->format('%y');
        if ($total_years > 0)
        {
            $cake_icon = '<img src="/templates/default/images/cake.png" alt="'.$total_years.' years" class="tooltip-top" title="'.$username.' has been here for '.$total_years.' years" />';
        }
    }
    return $cake_icon;
}

Example dates:

Registered - 19 February 2022 at 8:55 pm UTC (as a timestamp 1645304121)
Today - 19 February 2024 at 11:22 am UTC

It ends up only saying it has been 1 year.

What am I doing wrong?

2

Answers


  1. This is essentially a rounding issue: at 11:22AM, the user has only been registered for 1 year, 364 days, and a few hours. You want to display "how many years, to the nearest day", but PHP has no way to know that.

    One way to solve that would be to truncate each of the timestamps you’re comparing to midnight, then compare them.

    Note that using DateTimeImmutable, where each modification creates a new object rather than modifying the current one, is often clearer. Also, instead of ->format('%y') you can access the ->y property on the difference to get an integer number of years.

    $registrationTime = new DateTimeImmutable('19 February 2022 8:55 pm UTC');
    $now = new DateTimeImmutable('19 February 2024 11:22 am UTC');
    
    $registrationDateOnly = $registrationTime->setTime(0, 0, 0, 0);
    $today = $now->setTime(0, 0, 0, 0);
    
    $totalYears = $registrationDateOnly->diff($today)->y;
    
    var_dump($totalYears);  // int(2)
    
    Login or Signup to reply.
  2. Take the current year as your basis from $reg_date. Subtract it from the current year. This way you will know the number of calendaristic years between the two.

    Then, compare the latter part of the two dates and if we are later in the current year than the registration timestamp was in its year, then subtract one.

    So:

    $year1 = intval($date1->format("Y"));
    $year2 = intval($date2->format("Y"));
    $yeardifference = $year2 - $year1;
    $yearStart1 = new DateTime();
    $yearStart1->setDate($year1->format('Y'), 1, 1);
    $diff1 = date_diff($date1, $yearStart1);
    $yearStart2 = new DateTime();
    $yearStart2->setDate($year2->format('Y'), 1, 1);
    $diff2 = date_diff($date1, $yearStart2);
    if ($diff1 > $diff2) {
        $yeardifference--;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search