有没有可能在不使用网络服务的情况下确定点(lat / lon)的时区? Geonames.org对我来说不够稳定 :( 我需要这个在PHP中工作。
谢谢
有没有可能在不使用网络服务的情况下确定点(lat / lon)的时区? Geonames.org对我来说不够稳定 :( 我需要这个在PHP中工作。
谢谢
你需要多精确的结果?如果粗略估计足够了,就自己计算偏差:
offset = direction * longitude * 24 / 360
方向为1表示东,为-1表示西,经度在(-180, 180)之间。
我在处理另一个项目时遇到了这个问题,并深入研究了它。 我发现所有现有的解决方案在很大程度上都存在缺陷。
下载GeoNames数据并使用某些空间索引查找最近点肯定是一种选择,并且通常会产生正确的结果,但如果查询点与数据库中最近点之间跨越时区边界,它很容易失败。
更准确的方法是使用时区的数字地图,并编写代码以查找包含给定查询点的多边形。 幸运的是,在http://efele.net/maps/tz/world/(不再维护anymore)提供了世界时区的出色地图。 要编写高效的查询引擎,您需要:
每一个都值得有自己的Stack Overflow问题/答案页面。
在得出没有任何现有解决方案满足我的需求的结论后,我编写了自己的解决方案,并在这里提供了它:
AskGeo使用数字地图和高度优化的空间索引,使得在单个线程上在我的计算机上运行超过10,000个查询每秒都是可能的。它是线程安全的,因此甚至可以实现更高的吞吐量。这是一段严肃的代码,并且我们花了很长时间来开发它,所以我们提供商业许可证。
它是用Java编写的,因此在PHP中使用它需要使用:
http://php-java-bridge.sourceforge.net/doc/how_it_works.php
我们也愿意为奖金移植它。有关定价和详细文档,请参见http://askgeo.com。对于陆地上的区域,已经制作了一些关于tz(Olson)数据库时区的shapefile地图。虽然它们的更新频率不如tz数据库本身那么快,但这是一个很好的起点,并且在大多数情况下似乎非常准确。
// ben@jp
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') ;
if (lng < -139.5) {
if (lat < 68.5) {
if (lng < -140.5) {
return 371;
} else {
return 325;
}
因此,我认为将其翻译成PHP应该很容易。