23

Is there a way get the timezone of a user by their latitude and longitude? And not just the offset, but the actual timezone they're in.

Essentially, I'm searching for the polar opposite of DateTimeZone::getLocation which returns the latitude and longitude for a certain timezone.

1
  • Yeah it was.. I had looked into geonames before but from what I could tell it didn't give the actual timezone NAME. Boy was I wrong and boy do I feel stupid now. Commented Jun 28, 2010 at 10:31

6 Answers 6

33

For those who wants to get timezone from country code, latitude and longitude. ( easy to get it if you have a geoip module installed on your server )

Try this, I've added a distance calculation - only for those countries which has multiple timezones. Ah, and the country code is a two letter ISO code.

// ben@jp

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';
}
//timezone for one NY co-ordinate
echo get_nearest_timezone(40.772222,-74.164581) ;
// more faster and accurate if you can pass the country code 
echo get_nearest_timezone(40.772222, -74.164581, 'US') ;
Sign up to request clarification or add additional context in comments.

3 Comments

This might be a better answer. I'd have to do some testing. Why the country code at all? Are there locations that are in multiple countries?
Great,... some time wrong time zone , but works accurate while using with country code
Because this is calculating by distance, if you put in coordinates from Seattle you get America/Boise instead of America/Los_Angeles. I found it more accurate to take the difference in longitude and use that instead ie $distance = abs(abs($curLong) - abs($tzLong));
5

Geonames should do the job nicely:

http://www.geonames.org/

They've also got a php library.

1 Comment

GeoNames finds the time zone for the nearest record in their database. If that record is on the other side of a time zone border, it will be wrong.
4

A good resource is the Google Time Zone API.

Documentation: https://developers.google.com/maps/documentation/timezone/

It takes latitude and longitude and returns array like this:

array(
    'dstOffset' => (int) 3600,
    'rawOffset' => (int) -18000,
    'status' => 'OK',
    'timeZoneId' => 'America/New_York',
    'timeZoneName' => 'Eastern Daylight Time'
)

...but there are some limits:

[updated 2019] The Google Time Zone API has usage limits in place. Basically, billing must be enabled on your project, but a $200 USD "Google Maps Platform credit" is applied each month (so in most cases your first 40,000 Time Zone API calls/month would be free of charge).

Comments

0

I did a timezone solution recently in an 8 hour long hackathon. It's quickly put together and I'd love to develop it further and sell it as a product but since there is no way for me to do it, I've open sourced it at my github.

There is a demo too but it may go down if it hits resource limits. It's a free webapp on Google App Engine.

You can definitely optimize/augment this further in wrt - running time, space, data - to suit your needs.

1 Comment

Did you miss "PHP" in the question? There is a much better solution for Python already available: github.com/MrMinimal64/timezonefinder
-3

The Yahoo places API provides timezone information via reverse geolocation.

Check it out.

http://developer.yahoo.com/geo/placefinder/guide/requests.html

1 Comment

yahoo stopped supporting their GPS products last year and licensed the technology to Nokia, not a company with the best of outlooks for the future, unless they fire their Microsoft planted development chief and join the android bandwagon before the company runs out of spunk.
-3

How about finding the closest point to the one in the list of all timezone locations? I wonder how accurate is this?

UPDATE: Eventually, I came up with this snippet that works for me. This will work fine for all locations, but may not be accurate for those close to borders.

  /**
   * Attempts to find the closest timezone by coordinates
   *
   * @static
   * @param $lat
   * @param $lng
   */
  public static function getClosestTimezone($lat, $lng)
  {
    $diffs = array();
    foreach(DateTimeZone::listIdentifiers() as $timezoneID) {
      $timezone = new DateTimeZone($timezoneID);
      $location = $timezone->getLocation();
      $tLat = $location['latitude'];
      $tLng = $location['longitude'];
      $diffLat = abs($lat - $tLat);
      $diffLng = abs($lng - $tLng);
      $diff = $diffLat + $diffLng;
      $diffs[$timezoneID] = $diff;

    }

    //asort($diffs);
    $timezone = array_keys($diffs, min($diffs));


    return $timezone[0];

  }

3 Comments

This is very incorrect, as it treats each time zone as having a single latitude and latitude. It won't be a little inaccurate near borders, it will be horribly inaccurate over vast areas of the globe.
@James D, I agree you can't rely on this solution if you need a precise solution of timezone identification, but it is totally fine to suggest a user to choose among the list of timezones closest to his location. I find this approach better than just giving a huge list of timezones.
Timezone is not strictly based on LatLong, there are also political considerations involved. Singapore is in the same timezone as HongKong, though it significantly west of Hong Kong, and though it is in the same longitude as Jakarta, it is one hour ahead of Jakarta. Attempting a Timezone calculation strictly on lat/long without mapping them out is a bad idea.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.