如何在 PHP 中通过 IP 地址获取时区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/743505/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 23:43:14  来源:igfitidea点击:

How to get Time Zone through IP Address in PHP

phptimetimezoneip

提问by Devesh M

I want to get time zone through an IP Address in PHP. Actually, I have an application which will run at the client machine. I have the IP address of the client machine. But I am not able to get the time zone for each client machine.

我想通过 PHP 中的 IP 地址获取时区。实际上,我有一个将在客户端计算机上运行的应用程序。我有客户端机器的 IP 地址。但我无法获得每台客户端机器的时区。

回答by Chandrika Shah

$ip = "189.240.194.147";  //$_SERVER['REMOTE_ADDR']
$ipInfo = file_get_contents('http://ip-api.com/json/' . $ip);
$ipInfo = json_decode($ipInfo);
$timezone = $ipInfo->timezone;
date_default_timezone_set($timezone);
echo date_default_timezone_get();
echo date('Y/m/d H:i:s');

Sometime it won't work on local server so try on server.

有时它在本地服务器上不起作用,所以在服务器上尝试。

Edit: This data is coming from ip-api.com, they're free to use as long as you don't exceed 45 requests per minuteand not using commercially. See their TOS, not a long a page.

编辑:此数据来自ip-api.com,只要您每分钟不超过45 个请求并且不用于商业用途,它们就可以免费使用。看他们的TOS,不是很长的一页。

回答by John Saunders

IP address can't even be relied upon to map to a country; you're treading on thin ice if you also want to get timezone. You're better off to have the client sendyou the time zone, perhaps in a header.

甚至不能依赖 IP 地址来映射到一个国家;如果您还想获得时区,那您就如履薄冰。您最好让客户端发送时区,也许在标题中。

See Tor: anonymity onlinefor yet another reason to stop using IP addresses for things they were not designed for.

请参阅Tor:匿名在线,这是停止将 IP 地址用于非设计用途的另一个原因。

回答by vartec

If you're running it on the local machine, you can check the configured timezone.
http://www.php.net/manual/en/function.date-default-timezone-get.php

如果你在本地机器上运行它,你可以检查配置的时区。
http://www.php.net/manual/en/function.date-default-timezone-get.php

There are a lot better and more reliable methods then trying to guess timezone using GeoIP. If you're feeling lucky, try: http://www.php.net/manual/en/book.geoip.php

有很多更好、更可靠的方法来尝试使用 GeoIP 猜测时区。如果您感到幸运,请尝试:http: //www.php.net/manual/en/book.geoip.php

$region = geoip_region_by_name('www.example.com');
$tz = geoip_time_zone_by_country_and_region($region['country_code'],
                                            $region['region']);  

回答by cgp

There's no absolutely certain way to get the client's timezone, but if you have the client submit the date and time from their machine, you can compute it based on what the time it is relative to GMT. So, if it's 7:00pm on their machine and it's 12:00am GMT, then you can determine they are -5 from GMT or (EST/DST)

没有绝对确定的方法来获取客户端的时区,但是如果您让客户端从他们的机器提交日期和时间,您可以根据它相对于 GMT 的时间来计算它。因此,如果在他们的机器上是晚上 7:00 并且是格林威治标准时间上午 12:00,那么您可以确定它们是格林威治标准时间的 -5 或 (EST/DST)

回答by masud_moni

It is not a good idea for searching the timezone of a user through his or her ip address as he can access his or her account from different places at different times. So it is impossible to locate his timezone through ip address. But I have tried to find a solution and i am giving my code here. Any criticism about the coding technique will be highly appreciated.

通过用户的 ip 地址搜索用户的时区不是一个好主意,因为他或她可以在不同的时间从不同的地方访问他或她的帐户。所以不可能通过ip地址定位到他的时区。但我试图找到一个解决方案,我在这里提供我的代码。对编码技术的任何批评都将受到高度赞赏。

<?php

$time_zone = getTimeZoneFromIpAddress();
echo 'Your Time Zone is '.$time_zone;

function getTimeZoneFromIpAddress(){
    $clientsIpAddress = get_client_ip();

    $clientInformation = unserialize(file_get_contents('http://www.geoplugin.net/php.gp?ip='.$clientsIpAddress));

    $clientsLatitude = $clientInformation['geoplugin_latitude'];
    $clientsLongitude = $clientInformation['geoplugin_longitude'];
    $clientsCountryCode = $clientInformation['geoplugin_countryCode'];

    $timeZone = get_nearest_timezone($clientsLatitude, $clientsLongitude, $clientsCountryCode) ;

    return $timeZone;

}

function get_client_ip() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
        $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

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';
}

回答by Andy Gee

It's not straight forward but I get the time including daylight saving offset from 2 api calls using jquery and php. All of it could be done in PHP quite easily with a bit of adaptation. I'm sure this could be laid out differently too but I just grabbed it from existing code which suited my needs at the time.

这不是直截了当的,但我得到了时间,包括使用 jquery 和 php 的 2 个 api 调用的夏令时偏移量。所有这些都可以很容易地在 PHP 中完成,只需稍作调整。我确信这也可以以不同的方式布局,但我只是从当时适合我需要的现有代码中获取它。

Jquery/php:

jQuery/PHP:

function get_user_time(){
    var server_time = <? echo time(); ?>; //accuracy is not important it's just to let google know the time of year for daylight savings time
    $.ajax({
        url: "locate.php",
        dataType: "json",
        success: function(user_location) {
            if(user_location.statusCode=="OK"){
                $.ajax({
                    url: "https://maps.googleapis.com/maps/api/timezone/json?location="+user_location.latitude+","+user_location.longitude+"&timestamp="+server_time+"&sensor=false",
                    dataType: "json",
                    success: function(user_time) {
                        if(user_time.statusCode=="error"){
                            //handle error
                        }else{
                            user_time.rawOffset /= 3600;
                            user_time.dstOffset /= 3600;
                            user_real_offset = user_time.rawOffset+user_time.dstOffset+user_time.utc;
                            //do something with user_real_offset
                        }
                    }
                });
            }
        }
    });
}

locate.php

定位.php

function get_client_ip() {
    $ipaddress = '';
    if ($_SERVER['HTTP_CLIENT_IP'])
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if($_SERVER['HTTP_X_FORWARDED_FOR'])
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if($_SERVER['HTTP_X_FORWARDED'])
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if($_SERVER['HTTP_FORWARDED_FOR'])
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if($_SERVER['HTTP_FORWARDED'])
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if($_SERVER['REMOTE_ADDR'])
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';

    return $ipaddress;
}
$location = file_get_contents('http://api.ipinfodb.com/v3/ip-city/?key=xxxxxxxxx&ip='.get_client_ip().'&format=json');
$location = json_decode($location,true);
if(is_array($location)){
    date_default_timezone_set('UTC');
    $location['utc'] = time();
    echo json_encode($location);
}else{
    echo '{"statusCode":"error"}';
}

Register for a free key here: http://ipinfodb.com/register.php(no limits but queued if more than 1 request per second)

在此处注册免费密钥:http: //ipinfodb.com/register.php(没有限制,但如果每秒超过 1 个请求则排队)

回答by Pablo Santa Cruz

If what you need to know is the timezone of users browsing your webpage, then you can use some service like IP2LOCATIONto guess the timezone. Keep in mind though, as altCognito said, this is not a 100% accurate way of telling client's timezone. There are some accuracy problems with this approach.

如果您需要知道浏览您网页的用户所在的时区,那么您可以使用诸如IP2LOCATION 之类的服务来猜测时区。但是请记住,正如 altCognito 所说,这不是告诉客户时区的 100% 准确方法。这种方法存在一些准确性问题。

回答by Jamie

Check out the Maxmind GeoLite2 database. It contains details about the continent/country/city and lat/lon for most IP addresses including the time_zoneas you can see below.

查看 Maxmind GeoLite2 数据库。它包含有关大多数 IP 地址的大陆/国家/城市和纬度/经度的详细信息,包括time_zone,如下所示。

I describe how to compile the PHP extension, and how to use the mmdb databases in PHP here:

我在这里描述了如何编译 PHP 扩展,以及如何在 PHP 中使用 mmdb 数据库:

Intro to Maxmind GeoLite2 with Kohana PHP

使用 Kohana PHP 介绍 Maxmind GeoLite2

enter image description here

在此处输入图片说明

回答by user

Here's an example using a location APIthat maps IP address to timezone, e.g. send a request to https://ipapi.co/<IP-Address>/timezone/& get back timezone for that IP address.

这是一个使用将 IP 地址映射到时区的位置 API的示例,例如https://ipapi.co/<IP-Address>/timezone/,向该 IP 地址发送请求并取回时区。

PHP Code

PHP代码

file_get_contents('https://ipapi.co/1.2.3.4/timezone/');

Accuracy is not 100% as others have said.

正如其他人所说,准确度不是 100%。