从纬度和经度获取 PHP 时区名称?

发布于 2024-09-07 00:48:38 字数 113 浏览 7 评论 0 原文

有没有办法通过用户的纬度和经度获取时区?不仅仅是偏移量,还有它们所在的实际时区。

本质上,我正在寻找与 DateTimeZone::getLocation 相反的内容,它返回特定时区的纬度和经度。

Is there a way get the timezone of a user by their latitude and longitude? And not just the offset, but the actual timezone they're in.

Essentially, I'm searching for the polar opposite of DateTimeZone::getLocation which returns the latitude and longitude for a certain timezone.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

‘画卷フ 2024-09-14 00:48:38

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

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

// 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') ;

For those who wants to get timezone from country code, latitude and longitude. ( easy to get it if you have a geoip module installed on your server )

Try this, I've added a distance calculation - only for those countries which has multiple timezones.
Ah, and the country code is a two letter ISO code.

// 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') ;
庆幸我还是我 2024-09-14 00:48:38

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

http://www.geonames.org/

他们还有一个 php图书馆。

Geonames should do the job nicely:

http://www.geonames.org/

They've also got a php library.

但可醉心 2024-09-14 00:48:38

Google Time Zone API 是一个很好的资源。

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

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

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

...但有一些限制:

[2019 年更新] Google Time Zone API 设有使用限制。基本上,您的项目必须启用计费功能,但每月会应用 200 美元的“Google Maps Platform 积分”(因此在大多数情况下,您每月的前 40,000 次时区 API 调用将是免费的)。

A good resource is the Google Time Zone API.

Documentation: https://developers.google.com/maps/documentation/timezone/

It takes latitude and longitude and returns array like this:

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

...but there are some limits:

[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).

幼儿园老大 2024-09-14 00:48:38

我最近在一次长达 8 小时的黑客马拉松中做了一个时区解决方案。它很快就组装在一起了,我很想进一步开发它并将其作为产品出售,但由于我没有办法做到这一点,所以我在 我的 github

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

您绝对可以在运行时间、空间、数据方面进一步优化/增强这一点,以满足您的需求。

I did a timezone solution recently in an 8 hour long hackathon. It's quickly put together and I'd love to develop it further and sell it as a product but since there is no way for me to do it, I've open sourced it at my github.

There is a demo too but it may go down if it hits resource limits. It's a free webapp on Google App Engine.

You can definitely optimize/augment this further in wrt - running time, space, data - to suit your needs.

暖树树初阳… 2024-09-14 00:48:38

雅虎地点 API 通过反向地理定位提供时区信息。

一探究竟。

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

The Yahoo places API provides timezone information via reverse geolocation.

Check it out.

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

李白 2024-09-14 00:48:38

找到距离所有时区位置列表中最接近的点怎么样?我想知道这有多准确?

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

  /**
   * 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];

  }

How about finding the closest point to the one in the list of all timezone locations? I wonder how accurate is this?

UPDATE:
Eventually, I came up with this snippet that works for me. This will work fine for all locations, but may not be accurate for those close to borders.

  /**
   * 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];

  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文