IP Address to Time Zone Conversion: PHP’s Precision Approach

ali.wpsprintplan@gmail.com

Updated on:

You want to determine the time zone of a client machine based on its IP address in a PHP application. You have the IP address of the client machine, but you’re facing difficulties in obtaining the time zone information for each client machine. How can you achieve this in PHP?

<?php 
$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');
?>
o/p
America/Mexico_City2023/10/31 03:34:09

Sometimes, it may not function correctly on a local server, so you should attempt it on a live server.

This data is sourced from ip-api.com, and it’s available for free as long as you stay within their limits of not exceeding 45 requests per minute and refrain from using it for commercial purposes. You can refer to their terms of service (TOS) for more details, which is not a lengthy document.

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

This data is obtained from ip-api.com, and it’s free for use as long as you stay within the limits of not exceeding 45 requests per minute and not using it for commercial purposes. You can review their Terms of Service (TOS), which is a relatively short document.

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

?>
  o/p
Your Time Zone is Africa/Accra

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:

<?php
function get_user_time() {
    $server_time = time();
    // Echo the server time as a JavaScript variable
    echo "var server_time = $server_time;";
}
?>

     //accuracy is not important it's just to let google know the time of year for daylight savings time
  <script>
$(document).ready(function() {
    get_user_time();
});

function get_user_time() {
    var server_time; // Declare the variable
    $.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;
                            var user_real_offset = user_time.rawOffset + user_time.dstOffset + user_time.utc;
                            // Do something with user_real_offset
                        }
                    }
                });
            }
        }
    });
}
</script>

If you’re interested in determining the time zone of users who visit your webpage, you can utilize a service like IP2LOCATION to make an educated guess about their time zones. However, it’s essential to remember, as altCognito pointed out, that this method is not entirely precise in determining a client’s time zone, and there may be some accuracy issues with this approach.

Read more: How to Create a Custom Plugin in WordPress Like a Pro

Leave a Comment