есть ли возможность определить часовой пояс точки (lat/lon) без использования веб-сервисов? Geonames.org недостаточно стабилен для меня:( Мне нужно это для работы на PHP.
Спасибо
есть ли возможность определить часовой пояс точки (lat/lon) без использования веб-сервисов? Geonames.org недостаточно стабилен для меня:( Мне нужно это для работы на PHP.
Спасибо
У меня была эта проблема некоторое время назад, и я сделал то, что предложил адам:
IIRC потребовалось меньше 1 секунды, чтобы заполнить R-Tree, а затем выполнить тысячи поисков в секунду (как на 5-летнем ПК).
Насколько точны ваши результаты? Если приблизительной оценки достаточно, вычислите смещение самостоятельно:
offset = direction * longitude * 24 / 360
где направление 1 для востока, -1 для запада, а долгота - (-180,180)
Я столкнулся с этой проблемой, работая над другим проектом, и очень глубоко изучил ее. Я обнаружил, что во всех существующих решениях отсутствуют основные пути.
Загрузка данных GeoNames и использование некоторого пространственного индекса для поиска ближайшей точки - это определенно вариант, и он будет часто давать правильный результат, но он может легко потерпеть неудачу, если точка запроса находится не на той стороне времени граница зоны от ближайшей точки в базе данных.
Более точный метод состоит в том, чтобы использовать цифровую карту часовых поясов и написать код, чтобы найти многоугольник в той карте, которая содержит заданную точку запроса. К счастью, на http://efele.net/maps/tz/world/ есть отличная карта часовых поясов мира (больше не поддерживается). Чтобы написать эффективный механизм запросов, вам необходимо:
Каждый из них достоин своей страницы вопросов/ответов о переполнении стека.
Сделав вывод, что ни одно из существующих решений не отвечало моим потребностям, я написал собственное решение и сделал его доступным здесь:
AskGeo использует цифровую карту и имеет высоко оптимизированный пространственный индекс, который позволяет выполнять более 10000 запросов в секунду на моем компьютере в одном потоке. И это потокобезопасно, поэтому, конечно, возможна даже более высокая пропускная способность. Это серьезный кусок кода, и его разработка заняла много времени, поэтому мы предлагаем его по коммерческой лицензии.
Он написан на Java, поэтому его использование в PHP предполагает использование:
http://php-java-bridge.sourceforge.net/doc/how_it_works.php
Мы также открыты для портирования за вознаграждение. Для получения подробной информации о ценах и подробной документации см. Http://askgeo.com.
Я надеюсь, что это полезно. Это, безусловно, было полезно для проекта, над которым я работал.
Я знаю, что это старо, но я потратил некоторое время на поиски этого ответа. Нашел что-то очень полезное. Google выполняет поиск часовых поясов по long/lat. Нет свободного уровня больше: -/
Вы должны уметь, если знаете многоугольник часового пояса, чтобы увидеть, находится ли в нем данный lat/lon.
Для областей на суше есть некоторые карты шейп файла, которые были сделаны для часовых поясов базы данных tz (Olson). Они не обновляются так же регулярно, как и сама база данных tz, но это отличная отправная точка и кажется очень точной для большинства целей.
Как насчет этого?
// [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 'none?';
}
//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') ;
Я написал небольшой класс Java для этого. Его можно легко перевести на PHP. База данных встроена в сам код. Он точно до 22 км.
https://sites.google.com/a/edval.biz/www/mapping-lat-lng-s-to-timezones
Весь код в основном похож на это:
if (lng < -139.5) {
if (lat < 68.5) {
if (lng < -140.5) {
return 371;
} else {
return 325;
}
... поэтому я предполагаю, что перевод на PHP будет легким.
К сожалению, часовые пояса недостаточно регулярны для некоторой простой функции. См. Карту в Википедия - Часовой пояс
Однако может быть вычислено очень приблизительное приближение: 1-часовая разница соответствует 15 градусам долготы (360/24).
Еще одно решение - импортировать таблицу городов с часовыми поясами, а затем использовать формулу Хаверсина, чтобы найти ближайший город в этой таблице, соответствующий вашим координатам. Я разместил здесь полное описание: http://sylnsr.blogspot.com/2012/12/find-nearest-location-by-latitude-and.html
Для примера загрузки данных в MySQL я разместил здесь пример (с источниками для загрузки небольшого дампа данных): http://sylnsr.blogspot.com/2012/12/load-timezone-data-by-city-and-country.html
Обратите внимание, что точность поиска будет основана на том, насколько полны ваши данные поиска.
Кредиты и ссылки: Великое расстояние между MySQL (формула Хаверсина)
Вы можете использовать границы часовых поясов, указанные здесь:
Не уверен, что это полезно или нет, но я создал базу данных форм часового пояса (только для Северной Америки), которая кропотливо точна и актуальна не только для границ, но и для наблюдения за летним временем. Также формы для неофициальных исключений. Таким образом, вы можете запросить набор фигур для заданного местоположения, чтобы вернуть несколько фигур, которые применяются к этому местоположению, и выбрать правильный для времени года.
Вы можете увидеть изображение фигур в http://OnTimeZone.com/OnTimeZone_shapes.gif. Синие фигуры вокруг областей, которые не учитывают летнее время, пурпурные формируют те, которые наблюдают летнее время, и неоновые зеленые формы (маленькие и жесткие, чтобы видеть на этом уровне увеличения) предназначены для районов с неофициальным отклонением от официального часового пояса. Больше деталей о том, что доступно на сайте OnTimeZone.com.
Данные, доступные для загрузки на OnTimeZone.com, бесплатны для некоммерческого использования. Данные формы, которые недоступны для загрузки, доступны для коммерческой лицензии.
Я загрузил данные, которые соответствуют 5-значным почтовым индексам для часовых поясов, и данные, которые определяют смещение UTC для каждого часового пояса в периоды DST и не-DST.
Затем я упростил данные, чтобы рассматривать только первые три цифры почтового индекса, поскольку все почтовые индексы, которые разделяют первые три цифры, очень близки друг к другу; три цифры обозначают уникальный почтовый центр распространения.
Результирующий файл Json требует, чтобы вы определили, действительно ли вы подвергаетесь DST, и, вероятно, здесь есть некоторая неточность. Но это довольно хорошее локальное решение, которое очень компактно и просто для запроса.
Вот он: https://gist.github.com/benjiwheeler/8aced8dac396c2191cf0
Я использую geocoder.ca
Введите любое местоположение в Северной Америке, введите геокоды, коды областей и часовой пояс в json или jsonp.
Например: http://geocoder.ca/1600%20pennsylvania%20avenue,Washington,DC
Код города: (202) Часовой пояс: America/New_York
Json:
{"standard":{"staddress":"Pennsylvania Ave","stnumber":"1600","prov":"DC","city":"WASHINGTON","postal":"20011","confidence":"0.8"},"longt":"-76.972948","TimeZone":"America/New_York","AreaCode":"202","latt":"38.874533"}
Вы можете использовать Google Timezone api. https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=1331161200&key=YOUR_API_KEY
{
"dstOffset" : 0,
"rawOffset" : -28800,
"status" : "OK",
"timeZoneId" : "America/Los_Angeles",
"timeZoneName" : "Pacific Standard Time"
}
You can get the timezone based on the location in javascript.
function initAutocomplete() {
// Create the autocomplete object, restricting the search to geographical
// location types.
autocomplete = new google.maps.places.Autocomplete(
/** @type {!HTMLInputElement} */(document.getElementById('Location')),
{types: ['geocode']});
// When the user selects an address from the dropdown, populate the address
// fields in the form.
autocomplete.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
fnGettimezone($('#Location').serialize());
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
}
}
}
function fnGettimezone(location) {
$.ajax({
url: "http://maps.googleapis.com/maps/api/geocode/json?address=" + location + "&sensor=false",
dataType: 'json',
success: function (result) {
console.log(result);
// result is already a parsed javascript object that you could manipulate directly here
var myObject = JSON.parse(JSON.stringify(result));
lat = myObject.results[0].geometry.location.lat;
lng = myObject.results[0].geometry.location.lng;
console.log(myObject);
$.ajax({
url: "https://maps.googleapis.com/maps/api/timezone/json?location=" + lat + "," + lng + "×tamp=1331161200&sensor=false",
dataType: 'json',
success: function (result) {
// result is already a parsed javascript object that you could manipulate directly here
var myObject = JSON.parse(JSON.stringify(result));
$('#timezone').val(myObject.timeZoneName);
}
});
}
});
}
Этот проект создает шейп файл из данных OpenStreetMap и связывает его с несколькими библиотеками, которые его обрабатывают. Для PHP вы можете посмотреть на https://github.com/minube/geo-timezone