Ответ 1
Geonames должен хорошо выполнять работу:
У них также есть библиотека php.
Есть ли способ получить часовой пояс пользователя по их широте и долготе? И не только смещение, но и фактический часовой пояс, в котором они находятся.
По существу, я ищу полярную противоположность DateTimeZone:: getLocation, которая возвращает широту и долготу для определенного часового пояса.
Geonames должен хорошо выполнять работу:
У них также есть библиотека php.
Для тех, кто хочет получить часовой пояс из кода страны, широты и долготы. (легко получить его, если на вашем сервере установлен модуль 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') ;
Хорошим ресурсом является 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 часового пояса в месяц будут бесплатными).
Недавно я сделал часовое решение в хакеоне за 8 часов. Он быстро собрался, и я хотел бы развивать его дальше и продавать его как продукт, но поскольку для меня нет никакого способа сделать это, я открыл его на мой github.
Существует демонстрация, но она может снизиться, если она попадает в пределы ресурсов. Это бесплатный webapp в Google App Engine.
Вы можете определенно оптимизировать/увеличить это в дальнейшем, используя время, пространство, данные - в соответствии с вашими потребностями.
API-интерфейсы Yahoo предоставляет информацию о часовом поясе через обратную геолокацию.
Проверьте это.
http://developer.yahoo.com/geo/placefinder/guide/requests.html
Как найти ближайшую точку к той, что указана в списке всех мест часового пояса? Интересно, насколько это верно?
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];
}