spatie/google-time-zone
Convert GPS coordinates to time zone data using Google's Time Zone service. Get DST offset, raw offset, time zone ID, and time zone name from latitude and longitude. Works in plain PHP and Laravel projects, with a publishable config for your Google Maps API key and language setting.
Installation:
composer require spatie/google-time-zone
No additional configuration is required—just autoload the package.
First Use Case: Fetch the timezone for a given latitude/longitude (e.g., Brussels):
use Spatie\GoogleTimeZone\Facades\GoogleTimeZone;
$timezone = GoogleTimeZone::getTimeZoneForCoordinates('51.2194475', '4.4024643');
// Returns array with `timeZoneId`, `timeZoneName`, `rawOffset`, `dstOffset`.
Where to Look First:
Geocoding Integration:
Combine with spatie/laravel-geocoder to resolve addresses → coordinates → timezones:
$address = '1600 Amphitheatre Parkway, Mountain View, CA';
$coordinates = Geocoder::getCoordinates($address);
$timezone = GoogleTimeZone::getTimeZoneForCoordinates($coordinates['lat'], $coordinates['lng']);
Model Observers:
Auto-populate timezone fields on created/updated:
// User.php
protected static function boot()
{
parent::boot();
static::created(function ($user) {
$timezone = GoogleTimeZone::getTimeZoneForCoordinates($user->latitude, $user->longitude);
$user->timezone_id = $timezone['timeZoneId'];
$user->save();
});
}
API Responses: Normalize timezone data for consistency:
return response()->json([
'timezone' => [
'id' => $timezone['timeZoneId'],
'name' => $timezone['timeZoneName'],
'utc_offset' => $timezone['rawOffset'] + $timezone['dstOffset'],
],
]);
Caching: Cache responses for static coordinates (e.g., business locations):
$cacheKey = "timezone:{$lat}:{$lng}";
$timezone = Cache::remember($cacheKey, now()->addHours(1), function () use ($lat, $lng) {
return GoogleTimeZone::getTimeZoneForCoordinates($lat, $lng);
});
Bulk Lookups:
Use Laravel’s collect() to process multiple coordinates:
$coordinates = [['lat' => '51.2194', 'lng' => '4.4025'], ['lat' => '37.7749', 'lng' => '-122.4194']];
$timezones = collect($coordinates)->map(fn($coord) =>
GoogleTimeZone::getTimeZoneForCoordinates($coord['lat'], $coord['lng'])
);
Fallback Logic: Handle invalid coordinates gracefully:
try {
$timezone = GoogleTimeZone::getTimeZoneForCoordinates($lat, $lng);
} catch (\Spatie\GoogleTimeZone\Exceptions\InvalidCoordinates $e) {
$timezone = ['timeZoneId' => 'UTC']; // Default fallback
}
Rate Limits:
Invalid Coordinates:
InvalidCoordinates if coordinates are outside valid ranges (±90° latitude, ±180° longitude).if (!in_array($lat, range(-90, 90)) || !in_array($lng, range(-180, 180))) {
throw new \InvalidArgumentException("Invalid coordinates");
}
Daylight Saving Time (DST):
dstOffset is 0 when DST is inactive. Always use rawOffset + dstOffset for accurate UTC offsets.$utcOffset = $timezone['rawOffset'] + $timezone['dstOffset']; // e.g., 3600 (UTC+1) or 7200 (UTC+2)
API Key Requirements:
GoogleTimeZone::setApiKey('YOUR_API_KEY');
Testing:
GoogleTimeZone::shouldReceive('getTimeZoneForCoordinates')
->once()
->andReturn(['timeZoneId' => 'Europe/Paris']);
Performance:
timeZoneId (e.g., Europe/Brussels) over timeZoneName for comparisons—it’s standardized and cache-friendly.Extensions:
// app/Providers/AppServiceProvider.php
GoogleTimeZone::macro('getUtcOffset', function ($lat, $lng) {
$timezone = $this->getTimeZoneForCoordinates($lat, $lng);
return $timezone['rawOffset'] + $timezone['dstOffset'];
});
Usage:
$offset = GoogleTimeZone::getUtcOffset($lat, $lng);
Edge Cases:
UTC or no timezone. Handle with fallbacks.±90 may fail. Validate or use nearest valid coordinates.Logging:
try {
$timezone = GoogleTimeZone::getTimeZoneForCoordinates($lat, $lng);
} catch (\Exception $e) {
\Log::warning("Timezone lookup failed for {$lat},{$lng}: {$e->getMessage()}");
throw $e;
}
How can I help you explore Laravel packages today?