Carbon::diffForHumans

Renders the gap between two dates as a readable phrase such as '3 hours ago'.

Signature
public function diffForHumans($other = null, $syntax = null, $short = false, $parts = 1, $options = null): string
  • Added in Laravel Carbon 1.0

Parameters

ParameterTypeDescription
$$otheroptionalCarbon|DateTimeInterface|string|array|null= nullThe date to compare against. Null compares against the current moment. An array may be passed to supply the options below by name instead.
$$syntaxoptionalint|array|null= nullDirection of the phrasing: CarbonInterface::DIFF_ABSOLUTE drops "ago"/"from now", DIFF_RELATIVE_TO_NOW forces them, DIFF_RELATIVE_TO_OTHER produces "before"/"after". Null picks automatically.
$$shortoptionalbool= falseUse the abbreviated unit names of the current locale, such as "3h ago".
$$partsoptionalint= 1How many units to include. 1 gives "2 months ago"; 3 gives "2 months 1 week 5 days ago".
$$optionsoptionalint|null= nullBit mask of Carbon option constants, such as CarbonInterface::JUST_NOW, ONE_DAY_WORDS or TWO_DAY_WORDS, controlling wording near the boundaries.

Return value

stringA localized phrase describing the difference, such as "3 hours ago", "2 days from now" or "2 months before".

Changelog

  • PHP 2.0Gained the $short, $parts and $options arguments; earlier versions accepted only the comparison date and an absolute flag.

diffForHumans() turns a date difference into the phrase a timeline needs: "3 hours ago", "2 days from now", "2 months before". Called with no arguments it compares against the current moment and appends the direction; pass another date and it compares against that instead, switching the wording to "before" and "after".

Rounding is aggressive by default

Only the largest unit is reported, so 89 minutes reads as "1 hour ago" and a difference of 59 days reads as "1 month ago". Raise $parts when precision matters — $parts = 3 gives "2 months 1 week 5 days ago". Because the output collapses detail, never use it as a data value; keep the real timestamp in a title attribute alongside it.

Locale

The phrase is translated using Carbon's current locale, which Laravel sets from your application locale. Set it explicitly with $date->locale('es') for per-user rendering rather than relying on ambient state.

Testing it

Output depends on the clock, so freeze it with Carbon::setTestNow() or $this->freezeTime() before asserting on the string. Otherwise a test that passes at "1 second ago" fails a moment later at "2 seconds ago".

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Labelling activity feed entries with how long ago each event happened.
  • Showing how far in the future a scheduled job or event sits.
  • Describing the gap between two stored dates, such as signup and first purchase.

Frequently asked questions

How do I get more detail than '2 months ago'?

Pass a larger $parts value: diffForHumans(null, null, false, 3) produces '2 months 1 week 5 days ago'. The default of 1 reports only the largest unit and rounds everything below it away.

How do I remove the 'ago' suffix?

Pass CarbonInterface::DIFF_ABSOLUTE as the second argument, which yields '3 hours' instead of '3 hours ago'. Passing another date as the first argument instead switches the wording to 'before' and 'after'.

Why does the phrase change language between environments?

Because the output uses Carbon's current locale, which Laravel syncs with the application locale. Call ->locale('es') on the instance to pin it for a single render rather than depending on ambient configuration.

More examples

A timeline entry with the exact time in the title

The rounded phrase is what the reader scans, while the datetime attribute and title keep the exact value available to hover and to machines. Losing the precise timestamp is the usual regret when diffForHumans is used on its own.

Example · php
<?php

// resources/views/activity.blade.php
?>
<ul>
@foreach ($activities as $activity)
    <li>
        {{ $activity->description }}
        <time datetime="{{ $activity->created_at->toIso8601String() }}"
              title="{{ $activity->created_at->format('D, d M Y H:i') }}">
            {{ $activity->created_at->diffForHumans() }}
        </time>
    </li>
@endforeach
</ul>

Asserting on the output in a test

Ninety minutes rounds up to '2 hours ago' rather than reporting an hour and a half — the default single-unit output rounds to the nearest whole unit. Freezing the clock is what makes the assertion stable.

Example · php
<?php

use App\Models\Comment;
use Illuminate\Support\Carbon;

test('a comment shows a relative timestamp', function () {
    Carbon::setTestNow('2026-03-14 09:41:07');

    $comment = Comment::factory()->create([
        'created_at' => now()->subMinutes(90),
    ]);

    expect($comment->created_at->diffForHumans())->toBe('2 hours ago');

    Carbon::setTestNow();
});

Per-user locale

locale() is set on the instance, so it does not disturb the global locale other requests rely on. Carbon ships the translations, so no language files need to be published.

Example · php
<?php

use Carbon\Carbon;

Carbon::setTestNow('2026-03-14 09:41:07');

$posted = Carbon::parse('2026-03-14 06:41:07');

echo $posted->locale('en')->diffForHumans(), "\n"; // 3 hours ago
echo $posted->locale('es')->diffForHumans(), "\n"; // hace 3 horas
echo $posted->locale('fr')->diffForHumans(), "\n"; // il y a 3 heures

Carbon::setTestNow();

Discussion

  • Be the first to comment on this lesson.