Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Human Timestamps Laravel Package

chrisdicarlo/eloquent-human-timestamps

Adds human-readable accessors to Eloquent models so timestamp columns like created_at and updated_at can render as phrases such as "3 hours ago" or "in 2 days." Simple Laravel trait integration, customizable formatting, no schema changes needed.

View on GitHub
Deep Wiki
Context7

Getting Started

chrisdicarlo/eloquent-human-timestamps swaps Eloquent's default datetime handling for human-readable relative strings ("3 minutes ago", "2 weeks ago"), so your models expose friendly timestamps without every view having to call ->diffForHumans().

Requirements: PHP 8.x and Laravel 10/11/12. Note the compatibility matrix — Laravel 12 support landed only in v6.1.0, so pin ^6.1 if you're on Laravel 12; ^6.0 will fail dependency resolution there.

Minimal steps:

composer require chrisdicarlo/eloquent-human-timestamps
php artisan vendor:publish --tag="human-timestamps-config"   # optional, if you want to tweak output

Then opt in per model:

use ChrisDiCarlo\HumanTimestamps\HasHumanTimestamps;

class Comment extends Model
{
    use HasHumanTimestamps;
}

Where to look first: the trait source (it's a single small class — read it end to end before adopting it), then the published config for format/locale options, then the package tests to see the exact expected output shape.

First use case: an activity feed, comment list, or notification panel where every row renders "5 minutes ago". That's the sweet spot — read-only, display-oriented, low blast radius. Get it working on one throwaway model there before touching anything else.

Implementation Patterns

Roll out via a base model. Rather than sprinkling the trait, put it on an App\Models\BaseModel (or a HumanTimestamped concern) and let the models that need it extend that. It keeps the opt-in decision visible in one place and makes it trivial to remove if you change your mind.

Render in a Blade component, not inline. Wrap it in <x-relative-time :value="$comment->created_at" /> so you have exactly one place to change formatting or attach a <time datetime="..."> attribute for accessibility and machine-readability.

Keep a raw escape hatch. For anything that needs real date math or an ISO string (APIs, exports, sitemaps), pull the underlying value via $model->getRawOriginal('created_at') rather than trusting the accessor. Build a small helper so nobody has to remember which attribute returns what.

Separate display models from logic models. If a model's timestamps are used for sorting, SLA calculations, retention windows, or billing proration, do not put the trait on it. Instead, add an explicit accessor or API-resource method that formats the raw Carbon instance for display:

class CommentResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'created_at'     => $this->created_at->toIso8601String(),
            'created_at_ago' => $this->created_at->diffForHumans(),
        ];
    }
}

Testing. Freeze time so assertions are stable — $this->travelTo(...) in Laravel's test helpers, or Carbon::setTestNow(). Assert on the formatted string only where the format is the contract; elsewhere assert against the raw column.

Gotchas and Tips

Verify storage vs. accessor before you commit. Before shipping, inspect the column contents after a save (DB::table('comments')->first()). If the relative string is persisted rather than computed on read, you lose ordering, indexing, and range queries on that column — that's a schema-level decision, not a formatting one, and it should stop you for the models in question. Confirm this on your actual version rather than assuming.

Carbon methods silently disappear. If created_at comes back as a string, $model->created_at->addDay() fatals. Grep the codebase for ->created_at-> and ->updated_at-> before turning the trait on anywhere — this is the #1 breakage path.

Time-based queries. whereDate, whereBetween, latest('created_at'), and cursor pagination all assume a real datetime column. Test each one on any model you apply the trait to; an empty result set is easy to miss in a spot check.

Serialization shape changes. toArray() / toJson() will now emit a different string. Any consumer — a mobile client, an external API, a cached JSON blob — that parses those fields will break. Version your API or override serializeDate() if you need stability.

Page caching goes stale. This is the subtle one: a fragment or full-page cache holding "2 minutes ago" will keep serving "2 minutes ago" two days later. Either keep humanized output out of cached regions (render it client-side from an ISO timestamp) or keep cache TTLs short enough that staleness is invisible.

Locale. Relative strings follow the app locale. Set it per-request before rendering if you serve multiple languages, and be aware that stored strings won't retroactively translate.

Debugging. When output looks wrong, check $model->getAttributes() (what's actually in the column) versus $model->toArray() (what the accessor produced). The divergence tells you immediately whether the problem is storage, config, or the accessor.

Extension point. Subclass the trait or override the accessor in your base model if you need a custom format (e.g. abbreviated "3d" for tight table columns) — cleaner than post-processing strings in views.

Upgrade note. Beyond the Laravel 12 constraint, v6.1.0 is a compatibility release with no new API surface; the migration is a composer.json bump plus a full test run — pay particular attention to any date assertions and serialization snapshots.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core