anjan-talukdar / laravel-user-timezone
Seamless user timezone handling and dynamic Eloquent timestamp conversion for Laravel applications.
Package info
github.com/anjan-talukdar/laravel-user-timezone
pkg:composer/anjan-talukdar/laravel-user-timezone
Requires
- php: ^8.2
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
README
A lightweight, zero-boilerplate Laravel package that automatically displays timestamps and custom datetime columns in the user's local timezoneβwithout cluttering your Blade views, API resources, or controllers.
π Key Features
- Automatic Timezone Resolution Hierarchy:
- Authenticated User model setting (
$user->timezone) - Browser cookie (
user_timezone) auto-set via lightweight JS snippet - Session value (
session('user_timezone')) - Configured default fallback (
Asia/Kolkataor your custom default)
- Authenticated User model setting (
- Single Unified Trait (
HasUserTimezone):- Automatically converts standard timestamps (
created_at,updated_at,deleted_at). - Automatically converts any custom attribute declared in Eloquent
$castsas'datetime'.
- Automatically converts standard timestamps (
- Database Persistence Safety:
- Ensures dates are always stored in UTC in your database, while presenting them in local time upon retrieval and JSON serialization.
- Global Helper Function:
user_timezone()available anywhere in your application. - API & Serialization Ready: Automatically formats dates in JSON responses for REST APIs, Filament, Inertia.js, and Blade templates.
π Requirements
- PHP
^8.2 - Laravel
^10.0|^11.0|^12.0
π¦ Installation
Install the package via Composer:
composer require anjan-talukdar/laravel-user-timezone
Publish Configuration & Migrations
Publish the configuration file and database migration:
php artisan vendor:publish --tag="user-timezone-config" php artisan vendor:publish --tag="user-timezone-migrations"
Run the migration to add the timezone column to your users table:
php artisan migrate
βοΈ Configuration
The published configuration file config/user-timezone.php allows you to customize the default fallback timezone and cookie name:
return [ /* |-------------------------------------------------------------------------- | Default Timezone |-------------------------------------------------------------------------- | | Fallback timezone when no user or client browser timezone is detected. | */ 'default' => env('APP_TIMEZONE', 'Asia/Kolkata'), /* |-------------------------------------------------------------------------- | Cookie Name |-------------------------------------------------------------------------- | | The HTTP cookie key used by the frontend JS auto-detection script. | */ 'cookie_name' => 'user_timezone', ];
π» Usage
1. Eloquent Model Integration
Simply add the HasUserTimezone trait to your Eloquent models:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use AnjanTalukdar\UserTimezone\Traits\HasUserTimezone; class Post extends Model { use HasUserTimezone; protected $casts = [ 'published_at' => 'datetime', 'event_date' => 'datetime', ]; }
That's it! When accessing dates, they are automatically returned as Illuminate\Support\Carbon instances converted to the active user's local timezone:
$post = Post::find(1); // Standard timestamps automatically in user's timezone echo $post->created_at->format('Y-m-d H:i:s'); // Cast datetime attributes automatically in user's timezone echo $post->published_at->format('M j, Y g:i A'); // Access active timezone name echo $post->created_at->timezoneName; // e.g. "Asia/Kolkata" or "America/New_York"
2. Custom Formatting Helper Method
You can also use the model method formatUserDate() for inline formatting with custom fallback handling:
echo $post->formatUserDate('published_at', 'F j, Y, g:i a'); // Output: "July 29, 2026, 3:30 pm"
3. Global Helper Function
Access the resolved user timezone anywhere in controllers, Blade files, or services:
$currentTz = user_timezone(); // Returns e.g. "Asia/Kolkata" or "America/New_York"
4. Client-side Browser Auto-Detection
To automatically detect guest and logged-in user timezones via the browser, import the package JS snippet into your main JavaScript bundle (resources/js/app.js):
import 'path/to/packages/anjan-talukdar/laravel-user-timezone/resources/js/user-timezone.js';
Or add the standalone snippet directly in your HTML <head> or main layout:
<script> if (!document.cookie.includes('user_timezone=')) { const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; if (tz) { document.cookie = "user_timezone=" + encodeURIComponent(tz) + ";path=/;max-age=31536000;SameSite=Lax"; } } </script>
π How It Works Under the Hood
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. User Timezone Resolution β
β Auth User -> Browser Cookie -> Session -> Default β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β 2. Attribute Access ($model->created_at / $casts) β
β DB stores UTC βββΊ Carbon instance in User TZ β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β 3. Database Storage ($model->save()) β
β Carbon in User TZ βββΊ Converted back to UTC in DB β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Retrieval: When an attribute is retrieved (
created_at,updated_at,deleted_at, or any attribute cast as'datetime'),HasUserTimezoneintercepts the Carbon instance creation and applies.setTimezone(user_timezone()). - Serialization: When converting models to Array or JSON (
toArray(),toJson()), dates are formatted in the user's local timezone for API consumers. - Database Safety: When saving models, dates are converted back to UTC (or app default timezone) so your database records remain strictly synchronized and standardized in UTC.
π§ͺ Testing
Run package tests with PHPUnit:
vendor/bin/phpunit
π License
The MIT License (MIT). Please see License File for more information.
π¨βπ» Author
Anjan Talukdar
- GitHub: @anjan-talukdar