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

时间:2009-04-13 10:06:10

标签: php time timezone ip

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

10 个答案:

答案 0 :(得分:30)

获得一队卡车自行车,开车环游世界,记录每个人的无线路由器的IP地址和当前的GPS坐标。

这就是谷歌所做的。我是认真的。

更新:如果您负担不起,请使用MaxMind GeoLite2,它会按IP地址告诉您时区。它有一个本地PHP API(“数据库阅读器”)。

答案 1 :(得分:15)

甚至无法依靠IP地址映射到某个国家/地区;如果你还想获得时区,你就会在薄冰上行走。你最好让客户发送你的时区,也许是在标题中。

请参阅Tor: anonymity online,了解停止使用IP地址处理其不适合的内容的另一个原因。

答案 2 :(得分:15)

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

有时它无法在本地服务器上运行,因此请尝试使用服务器。

答案 3 :(得分:10)

如果您在本地计算机上运行它,则可以检查配置的时区。
http://www.php.net/manual/en/function.date-default-timezone-get.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']);  

答案 4 :(得分:10)

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

答案 5 :(得分:7)

通过他或她的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';
}

答案 6 :(得分:3)

这不是直截了当但我得到的时间包括使用jquery和php的2 api调用的夏令时偏移。所有这些都可以通过一些适应性很容易地在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

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

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

答案 7 :(得分:2)

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

答案 8 :(得分:1)

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

我将介绍如何编译PHP扩展,以及如何在PHP中使用mmdb数据库:

Intro to Maxmind GeoLite2 with Kohana PHP

enter image description here

答案 9 :(得分:0)

以下是使用location API将IP地址映射到时区的示例,例如:向https://ipapi.co/<IP-Address>/timezone/&amp;发送请求获取该IP地址的时区。

PHP代码

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

正如其他人所说的那样,准确性不是100%。