glhd/laravel-timezone-mapper
Laravel Timezone Mapper helps map IANA timezone identifiers to the values your app needs, with a clean Laravel integration and simple API. It makes timezone lookups and display easier in forms, APIs, and user settings.
No prior assessment existed for this package, so treat this as the baseline. 1.5.0 is a Laravel 13 compatibility release — it signals the package is maintained, but it does not introduce new end-user features.
First 15 minutes:
composer require glhd/laravel-timezone-mapper:^1.5 — but only if you're actually on Laravel 13. If you're on 11.x/12.x, pin ^1.4 and revisit after your own upgrade.composer.json picked up the service provider (Laravel 13 continues the no-manual-registration convention, so there should be nothing to add to bootstrap/providers.php).php artisan vendor:publish --tag="timezone-mapper-config" (check the README for the exact tag — tags are frequently renamed between majors and this one isn't a major).First use case: replace a free-text timezone field on the user profile with a validated select. Populate the options from the package, store the IANA identifier (America/New_York) on the user, and let Laravel's timezone cast plus a Rule::in(...) derived from the package do validation. That's the 80% case; everything else is variation on it.
Wrap it, don't sprinkle it. Put the package behind a small app-level service (App\Support\TimezoneOptions) with two methods — all(): array and label(string $tz): string. The package's public surface is small and has already churned across a minor-version Laravel-support bump; a one-class seam means a future 2.0 or a swap to brick/date-time is an afternoon, not a refactor.
Cache the option list, not the lookups. The dataset is static per release, so build the grouped [region => [id => label]] array once and Cache::rememberForever() it. Bust that key in your deploy script when the package version changes — a composer update silently changes what users see in a picker otherwise.
Store UTC, always. The mapper tells you which zone a user is in; it does not make local-time arithmetic safe. Persist timestampTz/UTC columns, convert at the edges (API resources, mailables, Blade), and never store an abbreviation like EST.
Middleware for request-scoped display. A small middleware that reads the authenticated user's mapped zone and calls Date::setTimezone() (or sets date_default_timezone_set) keeps controllers clean. Guard it: Auth::check() and a non-null zone, or you'll 500 on the login page.
Scheduling and reminders. Any "notify at 9am local" feature is where this package earns its keep — but do the arithmetic in the user's zone with Carbon::parse($time, $tz), convert to UTC for the queue, and add a test that runs across a DST boundary (e.g. America/New_York on the second Sunday in March). Half of all timezone bugs are one hour long and happen twice a year.
Validation layer. Prefer Rule::in(array_keys($options)) over Laravel's bare timezone rule when the picker is the only way in — it rejects identifiers the package doesn't render, which prevents "user picked something, UI shows blank" states.
Front-end integration. For Livewire, Filament, or Nova, feed the cached array into the native searchable select rather than building a custom component; timezone lists are ~400 entries and every framework's search-select handles them fine. Return {value: 'America/New_York', label: 'Eastern Time (New York)'} from your API resource so mobile clients don't reimplement the mapping.
1.5.0 is a constraint bump, not a feature. The changelog body is literally "Laravel 13 support + modern conventions," which means the real diff lives at the compare/1.4.0...1.5.0 link. Read it before upgrading. "Modern conventions" in a Glhd release typically means typed properties, added return types, and dropped deprecated helpers — all of which are breaking for subclasses even though the version is a minor.composer update will resolve you back to 1.4.x and you'll spend an hour wondering why the "upgrade" didn't happen. Check composer why-not glhd/laravel-timezone-mapper 1.5.0.^ on a Laravel-support release. If you support multiple Laravel versions in one codebase, constrain ^1.4|^1.5 deliberately rather than letting Composer choose per-environment.CST is Central Standard Time, China Standard Time, and Cuba Standard Time. If the package exposes abbreviation mapping, use it for labels; never for storage or comparison.Carbon::createSafe() and surface a validation error instead of silently shifting.1.5.0 adds or renames a config key, your published copy won't have it and you'll get silent defaults. Diff config/timezone-mapper.php against vendor/ after every minor upgrade.php artisan tinker, resolve a single identifier rather than dumping the whole collection — the dataset array is large enough to blow up output buffers and truncate the bit you wanted. If the mapping looks wrong, first check whether you're hitting a stale cache key from a previous package version.Timezone-style model, bind to the interface in your own container, not the concrete class, and avoid anything annotated @internal. This package's public API is deliberately small — don't expand your dependency on it by reaching into its guts.1.5.0 changelog. Verify the exact class names, config tags, and whether the mapping is dataset-backed or table-backed against the repo at 1.5.0 before committing to the integration approach; the workflow guidance above holds either way, but the deploy checklist differs.How can I help you explore Laravel packages today?