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(3mo ago)011MITPHPPHP ^8.2

Since Feb 2Pushed 3mo 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 1mo ago

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

36

—

LowBetter than 82% of packages

Maintenance81

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity46

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

100d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/0306a31e9423235a83c0093c7caaa9725e76e8796396ed3bc51225dd0cdaa4f1?d=identicon)[jeromejhipolito](/maintainers/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

[essa/api-tool-kit

set of tools to build an api with laravel

52680.5k](/packages/essa-api-tool-kit)[resend/resend-laravel

Resend for Laravel

1191.4M6](/packages/resend-resend-laravel)[smodav/mpesa

M-Pesa API implementation

16363.7k1](/packages/smodav-mpesa)[specialtactics/l5-api

Dependencies for the Laravel API Boilerplate package

3672.8k2](/packages/specialtactics-l5-api)[imliam/laravel-throttle-simultaneous-requests

Throttle the current user's requests based on how many requests are currently being executed.

4623.0k](/packages/imliam-laravel-throttle-simultaneous-requests)[shahghasiadil/laravel-api-versioning

Elegant attribute-based API versioning solution for Laravel applications with built-in deprecation management and version inheritance

2913.6k](/packages/shahghasiadil-laravel-api-versioning)

PHPackages © 2026

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