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

Laravel Timezone Mapper Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. 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.
  2. Confirm the auto-discovery entry in 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).
  3. Publish and read the config if the package ships one: 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).
  4. Open the source before the README. For a package named "timezone mapper," the single most important question is what is the source of the mapping — a bundled dataset, a generated PHP array, or a DB table with migrations/seeders. That answer changes your deploy checklist.

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.

Implementation Patterns

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.

Gotchas and Tips

  • 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.
  • Transitive PHP requirement jump. Laravel 13 raises the floor (8.3+). If your CI matrix pins 8.2, 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.
  • Don't trust the ^ 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.
  • Abbreviations are display-only. 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.
  • IANA identifiers are not permanent. Zones get renamed and merged between tzdata releases. Treat stored identifiers as user data: validate on read, and fall back to a default rather than throwing if a stored value no longer resolves.
  • DST edge cases are input-validation problems. A user picking "2:30am" on a spring-forward date gives you a time that doesn't exist. Use Carbon::createSafe() and surface a validation error instead of silently shifting.
  • Published config is frozen at publish time. If 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.
  • Debugging: in 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.
  • Extension points are thin by design. If the package exposes an interface or a 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.
  • Assessment confidence: this baseline is written from the package's purpose and the 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.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package