Get FrozenDate::diffForHumans() with years, months and days

Is there a method or a way to get the difference between two FrozenDates and show it in years, months and days

Is timeAgoInWords what you’re looking for?

I want to show the age of a patient in words, for example: 48 years 2 months 10 days, how do I have to write the timeAgoInWords so that it shows that string?
I am writing it like this: $edad = $team->pacient->birthday->timeAgoInWords(['format' => 'yyyy-MM-dd', 'accuracy' => ['year'=>'year','month'=>'month','day'=>'day'], 'from' => $date, 'absoluteString' => '%d años %d meses %d días']); and is giving me this exception: 4 arguments are required, 2 given.
The $date argument is created in AppController.php with this code:

$date = new FrozenDate(date('Y-m-d'));
$this->set('date', $date);

Where, specifically, does the “4 arguments are required, 2 given” exception get generated from? Clearly not from the line with the timeAgoInWords call, as that requires and is given one argument. So it must be some implementation detail down in there, and knowing specifically where would help with understanding what’s wrong with what you’re passing here.

This is the method where it gives the exception:

    public function dateAgoInWords(I18nDateTimeInterface $date, array $options = []): string
    {
        $options = $this->_options($options, FrozenDate::class);
        if ($options['timezone']) {
            $date = $date->timezone($options['timezone']);
        }

        $now = $options['from']->format('U');
        $inSeconds = $date->format('U');
        $backwards = ($inSeconds > $now);

        $futureTime = $now;
        $pastTime = $inSeconds;
        if ($backwards) {
            $futureTime = $inSeconds;
            $pastTime = $now;
        }
        $diff = $futureTime - $pastTime;

        if (!$diff) {
            return __d('cake', 'today');
        }

        if ($diff > abs($now - (new FrozenDate($options['end']))->format('U'))) {
            return sprintf($options['absoluteString'], $date->i18nFormat($options['format']));
        }

        $diffData = $this->_diffData($futureTime, $pastTime, $backwards, $options);
        [$fNum, $fWord, $years, $months, $weeks, $days] = array_values($diffData);

        $relativeDate = [];
        if ($fNum >= 1 && $years > 0) {
            $relativeDate[] = __dn('cake', '{0} year', '{0} years', $years, $years);
        }
        if ($fNum >= 2 && $months > 0) {
            $relativeDate[] = __dn('cake', '{0} month', '{0} months', $months, $months);
        }
        if ($fNum >= 3 && $weeks > 0) {
            $relativeDate[] = __dn('cake', '{0} week', '{0} weeks', $weeks, $weeks);
        }
        if ($fNum >= 4 && $days > 0) {
            $relativeDate[] = __dn('cake', '{0} day', '{0} days', $days, $days);
        }
        $relativeDate = implode(', ', $relativeDate);

        // When time has passed
        if (!$backwards) {
            $aboutAgo = [
                'day' => __d('cake', 'about a day ago'),
                'week' => __d('cake', 'about a week ago'),
                'month' => __d('cake', 'about a month ago'),
                'year' => __d('cake', 'about a year ago'),
            ];

            return $relativeDate ? sprintf($options['relativeString'], $relativeDate) : $aboutAgo[$fWord];
        }

        // When time is to come
        if ($relativeDate) {
            return $relativeDate;
        }
        $aboutIn = [
            'day' => __d('cake', 'in about a day'),
            'week' => __d('cake', 'in about a week'),
            'month' => __d('cake', 'in about a month'),
            'year' => __d('cake', 'in about a year'),
        ];

        return $aboutIn[$fWord];
    }

Is in class Cake\I18n\RelativeTimeFormatter, is where it says:

        if ($diff > abs($now - (new FrozenDate($options['end']))->format('U'))) {
            return sprintf($options['absoluteString'], $date->i18nFormat($options['format']));
        }

So, it’s sprintfing a single parameter into the absoluteString format provided, but you’ve given a format that demands three parameters. I haven’t used this function myself, so I can’t say how absoluteString is supposed to be used, but that’s the root of it.

I found out that I have to use relativeString instead of absoluteString, but I don’t know how to pass the relativeString so that it shows the age in xx years, xx months, xx days, and what should I put as end in the array.
Now I have it like this: $edad = $team->pacient->birthday->timeAgoInWords(['from' => $date, 'end' => '1000 years', 'relativeString' => '%d años %d meses %d semanas %d días']); but is giving me the exception 5 arguments are required, 2 given in these lines:

        if (!$backwards) {
            $aboutAgo = [
                'day' => __d('cake', 'about a day ago'),
                'week' => __d('cake', 'about a week ago'),
                'month' => __d('cake', 'about a month ago'),
                'year' => __d('cake', 'about a year ago'),
            ];

            return $relativeDate ? sprintf($options['relativeString'], $relativeDate) : $aboutAgo[$fWord];
        }

I could solve it, I had to pass the ‘relativeString’ => ‘%s’ and with that worked perfect