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

Timezone Laravel Package

laravel-validation-rules/timezone

Validate timezone input in Laravel with a dedicated timezone rule that checks values against PHP's supported timezone identifiers. Drop it into form requests or inline validators for a clear, reusable alternative to regex guessing.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require laravel-validation-rules/timezone

The package is auto-discovered and needs no publish step or config file. The main export is a rule object (namespace LaravelValidationRules\Timezone\Timezone), so it drops into the standard Laravel validation pipeline alongside string rules:

use LaravelValidationRules\Timezone\Timezone;

$validated = $request->validate([
    'timezone' => ['required', 'string', new Timezone()],
]);

Where to look first: open the rule class in src/ and read its passes() and message() methods — that tells you exactly what list it validates against (normally PHP's DateTimeZone::listIdentifiers()) and what error string your users will see. Then skim the changelog linked in the 1.7.0 release notes; the release notes themselves contain only that link, so there are no documented breaking changes or new APIs to design around.

First use case: the "where should we send your digest?" field in profile settings. Store the IANA identifier (e.g. Europe/Lisbon) in a string column and later resolve it with now($user->timezone) or $date->setTimezone($user->timezone).

Implementation Patterns

FormRequest — the default home for the rule. Keep controllers thin and put the rule in rules():

class UpdateProfileRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name'     => ['required', 'string', 'max:255'],
            'timezone' => ['required', 'string', new Timezone()],
        ];
    }
}

Multi-select / notification preferences. Validate the whole collection, not just the field:

'digest_timezones'   => ['array', 'max:5'],
'digest_timezones.*' => ['string', new Timezone()],

Allowlists narrower than "the whole planet." If the UI only offers a curated set (say, the business operates in three regions), compose the package rule with Rule::in() rather than replacing it — you get both the "is this even a real timezone?" check and your product constraint:

'timezone' => ['required', 'string', new Timezone(), Rule::in($this->allowedZones())],

Scheduling and reminders. The validated value is the value you hand to Carbon; treat validation as the single gate and never re-derive the zone from the browser later:

$user->update($request->validated());

$sendAt = $user->digest_at->setTimezone($user->timezone);

Livewire / Filament / Inertia forms. Because it is a rule object and not a string alias, use new Timezone() inside $this->validate([...]) or a Rule array in Filament's ->rules([...]). If you want the terse string form ('timezone' => 'timezone') across dozens of forms, register an alias once in a service provider via Validator::extend('timezone', ...) delegating to the package rule — but only if you actually feel the boilerplate.

Testing. Assert the contract, not the implementation:

$response = $this->post('/profile', ['timezone' => 'Mars/Olympus_Mons']);
$response->assertSessionHasErrors('timezone');

$this->post('/profile', ['timezone' => 'America/New_York'])->assertRedirect();

Validate through the HTTP layer or a Validator::make() call rather than instantiating the rule directly — that way a future major version that changes the constructor signature won't break your suite.

Gotchas and Tips

Offsets and abbreviations are not IANA identifiers. +02:00, GMT+2, and EST are not in DateTimeZone::listIdentifiers(). A picker that submits EST will fail validation even though it looks valid to a user. Decide up front whether you accept abbreviations (store them separately, map to an IANA zone) or force the picker to emit full identifiers. UTC is valid and is the usual safe fallback.

tzdata differences between environments. The list comes from PHP's bundled/inherited timezone database. A zone that validates on your laptop can fail on an older Docker base image (and vice versa). Pin your PHP image and, if you cache validation results or store allowlists, regenerate them at deploy time rather than committing them.

Column length. IANA names are longest around America/Argentina/ComodRivadavia (30 chars); don't leave a VARCHAR(20) migration behind from the first draft. string('timezone', 64) is a safe ceiling.

Backward-compatibility zones. Some identifiers are deprecated aliases. If you need to accept them, check whether your installed version exposes a way to widen the list (e.g. DateTimeZone::ALL_WITH_BC); otherwise normalise on input with a mapping table before validation.

Don't hand-roll timezone_identifiers_list(). That's precisely what this package wraps; duplicating it means you own the tzdata edge cases and the error message. If you genuinely need different behaviour (country-scoped zones, offsets), write a wrapper rule that delegates to the package for the base case instead of forking the logic.

Error message customisation. Override per-field with 'timezone.invalid'-style keys, or per-rule by extending the class and overriding message(). Prefer the translation file — a generic "The timezone is invalid" is confusing in a dropdown UI where the value came from your own options; "Please pick a timezone from the list" resolves support tickets.

Not a string rule. 'timezone' => 'timezone' will throw "Method does not exist" unless you registered the alias yourself. This trips people up when copy-pasting examples from packages that ship Rule macros or validation extensions; read the README's usage snippet literally.

Upgrading to 1.7.0. The release notes expose only a compare link — no breaking changes, removals, or new features are documented. Treat it as a low-risk minor: composer update laravel-validation-rules/timezone, run your validation tests, and check the changelog diff if you depend on constructor options or the exact error message string.

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.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json