0

Laravel 7.x

I need to access the timezone from where the application was accessed. I am only getting UTC in return from echo date_default_timezone_get();.

But I need to get something like Asia/Kolkata in return. For the access logs.

Mr.Singh
  • 1,421
  • 6
  • 21
  • 46

2 Answers2

0

As said in the comments, you can only make a guess, but not have 100% sure.

I made some modifications to Chandra Nakka's function.

It will validate the guess with the timezone_identifiers_list() function, if it's not a valid timezone, the default will be returned.

function set_timezone_by_client_location($ip = NULL, $deep_detect = TRUE) {
    $output = NULL;
    if (filter_var($ip, FILTER_VALIDATE_IP) === FALSE) {
        $ip = $_SERVER["REMOTE_ADDR"];
        if ($deep_detect) {
            if (filter_var(@$_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP))
                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
            if (filter_var(@$_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP))
                $ip = $_SERVER['HTTP_CLIENT_IP'];
        }
    }
    $continents = array(
        "AF" => "Africa",
        "AN" => "Antarctica",
        "AS" => "Asia",
        "EU" => "Europe",
        "OC" => "Australia",
        "NA" => "America",
        "SA" => "America"
    );
    $timezone = null;
    if (filter_var($ip, FILTER_VALIDATE_IP)) {
        $ipdat = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
        if (@strlen(trim($ipdat->geoplugin_countryCode)) == 2) {
          $timezone = @$continents[strtoupper($ipdat->geoplugin_continentCode)] . '/' . @$ipdat->geoplugin_regionName;
          $timezone = str_replace(' ', '_', $timezone);
        }
    }


    if(!in_array($timezone, timezone_identifiers_list())){
      $timezone = date_default_timezone_get();
    }

    return $timezone;
}

$timezone = set_timezone_by_client_location();

echo $timezone;
Lucius
  • 1,246
  • 1
  • 8
  • 21
  • Thanks @Lucius, based on your answer I have created a class of my own. And its working fine for me. I'll post it shortly. Thanks again :) – Mr.Singh Feb 13 '21 at 15:03
0

Framework: Laravel 7.x

namespace App\Services;

class TimeZoneService
{
    /**
     * Protected Variables
     */
    protected $host   = null;
    protected $filter = null;
    protected $ip     = null;
    protected $json   = null;

    public function __construct($ip, $filter = false)
    {
        $this->ip     = $ip;
        $this->filter = $filter;
        $this->host   = "http://www.geoplugin.net/json.gp?ip={$ip}";
    }

    /**
     * fetch the location data via given IP address
     *
     * @return  array
     */
    public function getData()
    {
        if(function_exists('curl_init'))
        {
            # use cURL to fetch data
            $request = curl_init();

            # setting options
            curl_setopt($request, CURLOPT_URL, $this->host);
            curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($request, CURLOPT_USERAGENT, 'geoPlugin PHP Class v1.1');

            # response
            $this->json = curl_exec($request);

            # closing cURL
            curl_close($request);
        }
        else if (ini_get('allow_url_fopen'))
        {
            # fall back to fopen()
            $this->json = file_get_contents($this->host, 'r');
        }
        else
        {
            trigger_error('geoPlugin Error: Cannot retrieve data.', E_USER_ERROR);
            return;
        }

        # returning
        return $this;
    }

    /**
     * convert the json string to php array 
     * based on the filter property
     *
     * @return  array
     */
    public function toArray()
    {
        # condition(s)
        if($this->filter != true)
        {
            return json_decode($this->json, true);
        }

        # filtering & returning
        return $this->__filter();
    }

    /**
     * convert the json string to php object 
     * based on the filter property
     *
     * @return  object
     */
    public function toObject()
    {
        # condition(s)
        if($this->filter != true)
        {
            return json_decode($this->json);
        }

        # filtering & returning
        return (object)$this->__filter();
    }

    /**
     * return collected location data in the form of json
     * based on the filter property
     *
     * @return  string
     */
    public function toJson()
    {
        # condition(s)
        if($this->filter != true)
        {
            return $this->json;
        }

        # filtering & returning
        return json_encode($this->__filter());
    }

    /**
     * filter the object keys
     *
     * @return  array
     */
    private function __filter()
    {
        # applying filter
        foreach(json_decode($this->json, true) as $key => $item)
        {
            $return[str_replace('geoplugin_', '', $key)] = $item;
        }

        # returning
        return $return;
    }
}

SomeController.php

/**
 * Services
 */
use App\Services\TimeZoneService;

class SomeController extends Controller
{
    public function someMethod()
    {
        # services
        $TimeZone = new TimeZoneService(<string IP_ADDRESS>, <boolean FILTER>);

        $locationData = $TimeZone->getData()->toJson();
        # OR
        $locationData = $TimeZone->getData()->toArray();
        # OR
        $locationData = $TimeZone->getData()->toObject();

        ...
    }
}

This code is working fine for me. However, If you see any room for improvement then please feel free to update the code to help others.

Thank you.

Mr.Singh
  • 1,421
  • 6
  • 21
  • 46