├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml ├── src ├── Facades │ └── TimezoneMapper.php ├── Initializer.php ├── Polygon.php ├── PolygonLookup.php ├── TimezoneMapper.php └── TimezoneMapperProvider.php ├── tests ├── TestCase.php └── TimezoneMapperTest.php └── timezones.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.phar 3 | composer.lock 4 | 5 | .DS_Store 6 | .idea/ 7 | .phpstorm.meta.php 8 | _ide_helper.php 9 | 10 | node_modules 11 | mix-manifest.json 12 | yarn-error.log 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Galahad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Timezone Mapper 2 | 3 | This package maps coordinates to a timezone string. Based heavily on [TimezoneMapperPHP](https://github.com/webmasterar/TimezoneMapperPHP) and [LatLongToTimezone](https://github.com/drtimcooper/LatLongToTimezone) and adopted for use in a Laravel project. 4 | 5 | It's not likely to be 100% correct every time, but if you need to map lots of coordinates and don't want to make API calls each time, it's a good way to get reasonable defaults. 6 | 7 | ## Usage: 8 | 9 | ```php 10 | $mapped_timezone = TimezoneMapper::mapCoordinates( 11 | latitude: 51.50853, 12 | longitude: -0.12574, 13 | fallback: 'America/New_York', // Optional -- used if unable to map coords 14 | ); 15 | 16 | // Returns "Europe/London" 17 | ``` 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glhd/laravel-timezone-mapper", 3 | "description": "Timezone mapper for Laravel", 4 | "keywords": [ 5 | "laravel", 6 | "timezone" 7 | ], 8 | "authors": [ 9 | { 10 | "name": "Chris Morrell", 11 | "homepage": "http://www.cmorrell.com" 12 | } 13 | ], 14 | "license": "MIT", 15 | "require": { 16 | "php": ">=7.1.3", 17 | "illuminate/support": "*" 18 | }, 19 | "require-dev": { 20 | "orchestra/testbench": "~3.0", 21 | "phpunit/phpunit": "^7.3", 22 | "mockery/mockery": "^1.1", 23 | "php-coveralls/php-coveralls": "^2.1" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Galahad\\TimezoneMapper\\": "src/" 28 | } 29 | }, 30 | "autoload-dev": { 31 | "classmap": [ 32 | "tests/TestCase.php" 33 | ], 34 | "psr-4": { 35 | "Galahad\\TimezoneMapper\\Tests\\": "tests/" 36 | } 37 | }, 38 | "minimum-stability": "stable", 39 | "extra": { 40 | "laravel": { 41 | "providers": [ 42 | "Galahad\\TimezoneMapper\\TimezoneMapperProvider" 43 | ], 44 | "aliases": { 45 | "TimezoneMapper": "Galahad\\TimezoneMapper\\Facades\\TimezoneMapper" 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests 14 | 15 | 16 | 17 | 18 | ./src 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Facades/TimezoneMapper.php: -------------------------------------------------------------------------------- 1 | points = $points; 12 | } 13 | 14 | public function contains($testy, $testx) : bool 15 | { 16 | $n = count($this->points); 17 | 18 | $yj = $this->points[$n - 2]; 19 | $xj = $this->points[$n - 1]; 20 | 21 | $inside = false; 22 | 23 | for ($i = 0; $i < $n;) { 24 | $yi = $this->points[$i++]; 25 | $xi = $this->points[$i++]; 26 | if ((($yi > $testy) !== ($yj > $testy)) && ($testx < ($xj - $xi) * ($testy - $yi) / ($yj - $yi) + $xi - 0.0001)) { 27 | $inside = !$inside; 28 | } 29 | $xj = $xi; 30 | $yj = $yi; 31 | } 32 | 33 | return $inside; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/TimezoneMapper.php: -------------------------------------------------------------------------------- 1 | lookup) { 14 | $this->timezones = require dirname(__DIR__).'/timezones.php'; 15 | $this->lookup = new PolygonLookup(Initializer::initialize()); 16 | } 17 | 18 | $index = $this->lookup->lookup($latitude, $longitude); 19 | 20 | if (!$index || !isset($this->timezones[$index])) { 21 | return $fallback; 22 | } 23 | 24 | return $this->timezones[$index]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/TimezoneMapperProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(TimezoneMapper::class); 13 | } 14 | 15 | public function provides() : array 16 | { 17 | return [ 18 | TimezoneMapper::class, 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | TimezoneMapper::class, 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/TimezoneMapperTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('America/Denver', $mapped_timezone); 17 | } 18 | 19 | public function test_it_returns_the_correct_timezone_for_philadelphia() : void 20 | { 21 | $philly_latitude = 39.952583; 22 | $philly_longitude = -75.165222; 23 | 24 | $mapped_timezone = TimezoneMapper::mapCoordinates($philly_latitude, $philly_longitude); 25 | 26 | $this->assertEquals('America/New_York', $mapped_timezone); 27 | } 28 | 29 | public function test_it_returns_the_correct_timezone_for_london() : void 30 | { 31 | $london_latitude = 51.50853; 32 | $london_longitude = -0.12574; 33 | 34 | $mapped_timezone = TimezoneMapper::mapCoordinates($london_latitude, $london_longitude); 35 | 36 | $this->assertEquals('Europe/London', $mapped_timezone); 37 | } 38 | 39 | public function test_it_returns_the_correct_timezone_for_shanghai() : void 40 | { 41 | $shanghai_latitude = 31.22222; 42 | $shanghai_longitude = 121.45806; 43 | 44 | $mapped_timezone = TimezoneMapper::mapCoordinates($shanghai_latitude, $shanghai_longitude); 45 | 46 | $this->assertEquals('Asia/Shanghai', $mapped_timezone); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /timezones.php: -------------------------------------------------------------------------------- 1 |