Laravel Carbon DiffForHumans Option (Years, Months, Days)

93 Views Asked by At

I have read through the documentation of DiffForHumans and it's very straightforward, but is there a way to customize the date to print out:

  • 13 Years, 1 Month, 10 Days
  • 01 Year, 11 Months, 01 Day

where it will respect the Year/Years, Month/Months, Day/Days?

  • Approach 1:

    $date = Carbon::parse('2010-08-29');
    $formattedDate = $date->diffForHumans(['parts' => 3, 'join' => ', '];
    

    Will print out 13 years, 1 month, 4 weeks ago

  • Approach 2:

    $date = Carbon::parse('2010-08-29');
    $formattedDate = $date->diff(now())->format('%y Year, %m Months and %d Days')
    

    Will print out 13 Year, 1 Months and 28 Days

  • Approach 3 (Backup option):

    $date = Carbon::parse('2010-08-29');
    $formattedDate = $date->diff(now())->format('%y Year(s), %m Month(s) and %d Day(s)')
    

    Will print out 13 Year(s), 1 Month(s) and 28 Day(s)

Is there a vanilla PHP class that could accomplish something similar?


Modified Accepted Solution:

public function customDiffForHumans(Carbon $date) : string
    {
        $diff = $date->diff(now());

        $years  = $diff->y ? $diff->y . ' Year' . ($diff->y > 1 ? 's' : '') : '0 Years';
        $months = $diff->m ? $diff->m . ' Month' . ($diff->m > 1 ? 's' : '') : '0 Months';
        $days   = $diff->d ? $diff->d . ' Day' . ($diff->d > 1 ? 's' : '') : '0 Days';

        return implode(', ', array_filter([$years, $months, $days]));
    }
3

There are 3 best solutions below

1
Jeyhun Rashidov On BEST ANSWER

That's the custom function for handling same problem:

function customDiffForHumans(DateTime $date) {
    $now = new DateTime();
    $diff = $date->diff($now);

    $years = $diff->y ? $diff->y . ' Year' . ($diff->y > 1 ? 's' : '') : null;
    $months = $diff->m ? $diff->m . ' Month' . ($diff->m > 1 ? 's' : '') : null;
    $days = $diff->d ? $diff->d . ' Day' . ($diff->d > 1 ? 's' : '') : null;

    return implode(', ', array_filter([$years, $months, $days]));
}

$date = new DateTime('2010-08-29');
return customDiffForHumans($date);
0
KyleK On

You can skip unit(s) you don't want:

$date = Carbon::parse('2010-08-29');
$formattedDate = $date->diffForHumans([
    'parts' => 3,
    'join' => true,
    'skip' => 'week',
]);

Side note: 'join' => true automatically use ,-and (and translate it if you select another language)

0
Odin Thunder On

You could try this example:

Carbon::parse('07-09-2014')->locale('en')->diffForHumans(
    [
        'parts' => 3,
        'join' => ', ',
        'skip' => 'week',
        'syntax' => Carbon::DIFF_ABSOLUTE,
    ]
)

Expected output:

"9 years, 1 month, 20 days"

But yes, this example will not cover leading zero and StudlyCase (you could use headline) issues