spatie/google-time-zone
Convert GPS coordinates to a time zone using Google’s Time Zone API. Fetch DST and raw offsets plus timeZoneId and timeZoneName for any latitude/longitude. Works in any PHP project, with optional Laravel config publishing and auto-discovery.
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?