关于地理位置:从纬度和经度中获取PHP时区名称?

Get PHP Timezone Name from Latitude and Longitude?

本问题已经有最佳答案,请猛点这里访问。

有没有办法通过纬度和经度获得用户的时区? 而不只是偏移量,而是它们所处的实际时区。

基本上,我正在搜索DateTimeZone :: getLocation的极性相反,它返回某个时区的纬度和经度。


对于那些想要从国家代码,纬度和经度获得时区的人。 (如果您的服务器上安装了geoip模块,则很容易获得)

试试这个,我添加了一个距离计算 - 仅适用于那些有多个时区的国家。
啊,国家代码是两个字母的ISO代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// 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 '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') ;


Geonames应该很好地完成这项工作:

http://www.geonames.org/

他们还有一个php库。


一个很好的资源是Google时区API。

文档:https://developers.google.com/maps/documentation/timezone/

它需要latitudelongitude并返回如下数组:

1
2
3
4
5
6
7
array(
    'dstOffset' => (int) 3600,
    'rawOffset' => (int) -18000,
    'status' => 'OK',
    'timeZoneId' => 'America/New_York',
    'timeZoneName' => 'Eastern Daylight Time'
)

......但是有一些限制:

[updated 2019] The Google Time Zone API has usage limits in place. Basically, billing must be enabled on your project, but a $200 USD"Google Maps Platform credit" is applied each month (so in most cases your first 40,000 Time Zone API calls/month would be free of charge).

  • Full details here and here.

我最近在8小时的黑客马拉松中做了一个时区解决方案。它很快就被整合在一起,我很乐意将它进一步发展并作为产品出售,但由于我无法做到这一点,我已经在我的github上开源了。

还有一个演示,但如果它达到资源限制可能会下降。它是Google App Engine上的免费网络应用程序。

您可以在运行时间,空间,数据方面进一步优化/扩充,以满足您的需求。


Yahoo places API通过反向地理定位提供时区信息。

看看这个。

http://developer.yahoo.com/geo/placefinder/guide/requests.html


如何找到所有时区位置列表中最接近的点?我想知道这有多准确?

更新:
最后,我想出了适合我的这个片段。这适用于所有位置,但对于靠近边界的人可能不准确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /**
   * 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];

  }