PHPackages                             jeromejhipolito/laravel-timezone-middleware - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. jeromejhipolito/laravel-timezone-middleware

ActiveLibrary[API Development](/categories/api)

jeromejhipolito/laravel-timezone-middleware
===========================================

Automatic timezone conversion middleware for Laravel APIs. Stores everything in UTC, converts request/response datetimes based on Accept-Timezone header.

v1.0.0(5mo ago)012MITPHPPHP ^8.2

Since Feb 2Pushed 5mo agoCompare

[ Source](https://github.com/jeromejhipolito/laravel-timezone-middleware)[ Packagist](https://packagist.org/packages/jeromejhipolito/laravel-timezone-middleware)[ RSS](/packages/jeromejhipolito-laravel-timezone-middleware/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (6)Versions (2)Used By (0)

Laravel Timezone Middleware
===========================

[](#laravel-timezone-middleware)

Automatic timezone conversion middleware for Laravel APIs. Stores everything in UTC, converts request/response datetimes based on the `Accept-Timezone` header.

Features
--------

[](#features)

- Automatically converts incoming request datetime values from user's timezone to UTC
- Automatically converts outgoing response datetime values from UTC to user's timezone
- Configurable datetime patterns for detection
- Exclude specific keys from conversion (e.g., birthdate)
- Exclude specific routes from conversion (e.g., webhooks)
- Supports nested arrays and JSON responses
- Zero configuration needed - works out of the box

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11.0+ or 12.0+

Installation
------------

[](#installation)

```
composer require jeromejhipolito/laravel-timezone-middleware
```

The package will auto-register its service provider.

Configuration
-------------

[](#configuration)

Publish the configuration file:

```
php artisan vendor:publish --tag=timezone-config
```

This will create `config/timezone.php`:

```
return [
    // HTTP header name for timezone detection
    'header' => env('TIMEZONE_HEADER', 'Accept-Timezone'),

    // Default timezone when no header is provided
    'default' => env('TIMEZONE_DEFAULT', 'UTC'),

    // Storage timezone (always UTC for consistency)
    'storage' => 'UTC',

    // Patterns to detect datetime strings in requests
    'request_patterns' => [
        '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/',
        '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/',
        '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/',
    ],

    // Patterns to detect datetime strings in responses
    'response_patterns' => [
        '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{6})?Z?$/',
        '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/',
    ],

    // Output format for response datetimes
    'response_format' => 'Y-m-d\TH:i:s.u\Z',

    // Output format for request datetimes (stored in DB)
    'request_format' => 'Y-m-d H:i:s',

    // Keys to exclude from conversion
    'excluded_keys' => [
        'birthdate',
        'date_of_birth',
        'dob',
    ],

    // Route patterns to exclude from conversion
    'excluded_routes' => [
        // 'api/webhooks/*',
    ],
];
```

Usage
-----

[](#usage)

### Register the Middleware

[](#register-the-middleware)

Add the middleware to your routes in `bootstrap/app.php`:

```
use JeromeJHipolito\TimezoneMiddleware\Middleware\TimezoneMiddleware;

->withMiddleware(function (Middleware $middleware) {
    $middleware->api(append: [
        TimezoneMiddleware::class,
    ]);
})
```

Or apply it to specific route groups:

```
use JeromeJHipolito\TimezoneMiddleware\Middleware\TimezoneMiddleware;

Route::middleware([TimezoneMiddleware::class])->group(function () {
    Route::get('/events', [EventController::class, 'index']);
    Route::post('/events', [EventController::class, 'store']);
});
```

### Client-Side Usage

[](#client-side-usage)

Clients should send their timezone in the `Accept-Timezone` header:

```
fetch('/api/events', {
    headers: {
        'Accept-Timezone': 'Asia/Manila',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        title: 'Meeting',
        scheduled_at: '2024-01-15 18:00:00', // User's local time
    }),
});
```

The middleware will:

1. **On Request**: Convert `scheduled_at` from `Asia/Manila` (UTC+8) to UTC before it reaches your controller

    - Input: `2024-01-15 18:00:00` (Manila time)
    - Stored: `2024-01-15 10:00:00` (UTC)
2. **On Response**: Convert all datetime values from UTC back to `Asia/Manila`

    - Stored: `2024-01-15 10:00:00` (UTC)
    - Response: `2024-01-15T18:00:00.000000Z` (Manila time)

### Excluding Fields

[](#excluding-fields)

Some fields shouldn't be timezone-converted (like birthdates). Add them to the `excluded_keys` config:

```
'excluded_keys' => [
    'birthdate',
    'date_of_birth',
    'dob',
    'anniversary_date',
],
```

### Excluding Routes

[](#excluding-routes)

Webhook endpoints often need raw UTC timestamps. Exclude them:

```
'excluded_routes' => [
    'api/webhooks/*',
    'api/callbacks/*',
],
```

### Getting the User's Timezone

[](#getting-the-users-timezone)

You can access the detected timezone in your application:

```
use JeromeJHipolito\TimezoneMiddleware\Middleware\TimezoneMiddleware;

public function show(Request $request)
{
    $middleware = app(TimezoneMiddleware::class);
    $userTimezone = $middleware->getUserTimezone();

    // Use it for custom formatting, etc.
}
```

How It Works
------------

[](#how-it-works)

```
┌─────────────────────────────────────────────────────────────────┐
│                         CLIENT                                   │
│  Timezone: Asia/Manila (UTC+8)                                  │
│  Sends: { "scheduled_at": "2024-01-15 18:00:00" }               │
│  Header: Accept-Timezone: Asia/Manila                           │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    TIMEZONE MIDDLEWARE                          │
│  Detects: Asia/Manila from header                               │
│  Converts: 18:00 Manila → 10:00 UTC                             │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      CONTROLLER                                  │
│  Receives: { "scheduled_at": "2024-01-15 10:00:00" }            │
│  Stores in DB as UTC                                            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      DATABASE                                    │
│  Stored: "2024-01-15 10:00:00" (UTC)                            │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    TIMEZONE MIDDLEWARE                          │
│  Converts response: 10:00 UTC → 18:00 Manila                    │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         CLIENT                                   │
│  Receives: { "scheduled_at": "2024-01-15T18:00:00.000000Z" }    │
│  Displays in user's local time                                  │
└─────────────────────────────────────────────────────────────────┘

```

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

Credits
-------

[](#credits)

- [Jerome Hipolito](https://github.com/jeromejhipolito)

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance73

Regular maintenance activity

Popularity5

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

153d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/180266815?v=4)[JeromeHipolito](/maintainers/jeromejhipolito)[@jeromejhipolito](https://github.com/jeromejhipolito)

---

Tags

middlewareapilaraveldatetimetimezoneutc

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/jeromejhipolito-laravel-timezone-middleware/health.svg)

```
[![Health](https://phpackages.com/badges/jeromejhipolito-laravel-timezone-middleware/health.svg)](https://phpackages.com/packages/jeromejhipolito-laravel-timezone-middleware)
```

###  Alternatives

[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M147](/packages/laravel-cashier)[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k9.0M69](/packages/spatie-laravel-responsecache)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M132](/packages/laravel-pulse)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.8k3](/packages/defstudio-telegraph)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
