How to get Time Zone through IP Address in PHP [du

2020-01-27 02:11发布

问题:

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.

回答1:

$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 minute and not using commercially. See their TOS, not a long a page.



回答2:

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 send you the time zone, perhaps in a header.

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



回答3:

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

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

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


回答4:

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)



回答5:

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.

<?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:

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:

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

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



回答7:

If what you need to know is the timezone of users browsing your webpage, then you can use some service like IP2LOCATION to 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.



回答8:

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

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

Intro to Maxmind GeoLite2 with Kohana PHP



回答9:

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

PHP Code

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

Accuracy is not 100% as others have said.