Получить имя часового пояса PHP из широты и долготы?

Есть ли способ получить часовой пояс пользователя по их широте и долготе? И не только смещение, но и фактический часовой пояс, в котором они находятся.

По существу, я ищу полярную противоположность DateTimeZone:: getLocation, которая возвращает широту и долготу для определенного часового пояса.

Ответы

Ответ 1

Geonames должен хорошо выполнять работу:

http://www.geonames.org/

У них также есть библиотека php.

Ответ 2

Для тех, кто хочет получить часовой пояс из кода страны, широты и долготы. (легко получить его, если на вашем сервере установлен модуль geoip)

Попробуйте это, я добавил расчет расстояния - только для тех стран, у которых есть несколько часовых поясов. Ах, а код страны - двухзначный код ISO.

// [email protected]

function get_nearest_timezone($cur_lat, $cur_long, $country_code = '') {
    $timezone_ids = ($country_code) ? DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country_code)
                                    : DateTimeZone::listIdentifiers();

    if($timezone_ids && is_array($timezone_ids) && isset($timezone_ids[0])) {

        $time_zone = '';
        $tz_distance = 0;

        //only one identifier?
        if (count($timezone_ids) == 1) {
            $time_zone = $timezone_ids[0];
        } else {

            foreach($timezone_ids as $timezone_id) {
                $timezone = new DateTimeZone($timezone_id);
                $location = $timezone->getLocation();
                $tz_lat   = $location['latitude'];
                $tz_long  = $location['longitude'];

                $theta    = $cur_long - $tz_long;
                $distance = (sin(deg2rad($cur_lat)) * sin(deg2rad($tz_lat))) 
                + (cos(deg2rad($cur_lat)) * cos(deg2rad($tz_lat)) * cos(deg2rad($theta)));
                $distance = acos($distance);
                $distance = abs(rad2deg($distance));
                // echo '<br />'.$timezone_id.' '.$distance; 

                if (!$time_zone || $tz_distance > $distance) {
                    $time_zone   = $timezone_id;
                    $tz_distance = $distance;
                } 

            }
        }
        return  $time_zone;
    }
    return 'unknown';
}
//timezone for one NY co-ordinate
echo get_nearest_timezone(40.772222,-74.164581) ;
// more faster and accurate if you can pass the country code 
echo get_nearest_timezone(40.772222, -74.164581, 'US') ;

Ответ 3

Хорошим ресурсом является API часовых поясов Google.

Документация: https://developers.google.com/maps/documentation/timezone/

Он принимает latitude и longitude и возвращает массив следующим образом:

array(
    'dstOffset' => (int) 3600,
    'rawOffset' => (int) -18000,
    'status' => 'OK',
    'timeZoneId' => 'America/New_York',
    'timeZoneName' => 'Eastern Daylight Time'
)

... но есть некоторые ограничения:

[обновлено 2019] В API часовых поясов Google установлены ограничения на использование. По сути, в вашем проекте должен быть включен биллинг, но ежемесячный "кредит Google Maps Platform" на сумму 200 долларов США применяется (поэтому в большинстве случаев ваши первые 40 000 вызовов API часового пояса в месяц будут бесплатными).

Ответ 4

Недавно я сделал часовое решение в хакеоне за 8 часов. Он быстро собрался, и я хотел бы развивать его дальше и продавать его как продукт, но поскольку для меня нет никакого способа сделать это, я открыл его на мой github.

Существует демонстрация, но она может снизиться, если она попадает в пределы ресурсов. Это бесплатный webapp в Google App Engine.

Вы можете определенно оптимизировать/увеличить это в дальнейшем, используя время, пространство, данные - в соответствии с вашими потребностями.

Ответ 6

Как найти ближайшую точку к той, что указана в списке всех мест часового пояса? Интересно, насколько это верно?

UPDATE: В конце концов, я придумал этот фрагмент, который работает для меня. Это будет хорошо работать для всех мест, но может быть неточным для тех, кто находится близко к границам.

  /**
   * Attempts to find the closest timezone by coordinates
   *
   * @static
   * @param $lat
   * @param $lng
   */
  public static function getClosestTimezone($lat, $lng)
  {
    $diffs = array();
    foreach(DateTimeZone::listIdentifiers() as $timezoneID) {
      $timezone = new DateTimeZone($timezoneID);
      $location = $timezone->getLocation();
      $tLat = $location['latitude'];
      $tLng = $location['longitude'];
      $diffLat = abs($lat - $tLat);
      $diffLng = abs($lng - $tLng);
      $diff = $diffLat + $diffLng;
      $diffs[$timezoneID] = $diff;

    }

    //asort($diffs);
    $timezone = array_keys($diffs, min($diffs));


    return $timezone[0];

  }