22

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.

j0k
  • 22,600
  • 28
  • 79
  • 90
Navarr
  • 3,703
  • 7
  • 33
  • 57
  • 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. – Navarr Jun 28 '10 at 10:31

6 Answers6

32

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') ;
j-bin
  • 671
  • 7
  • 9
5

Geonames should do the job nicely:

http://www.geonames.org/

They've also got a php library.

thomasfedb
  • 5,990
  • 2
  • 37
  • 65
  • 3
    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. – James D May 08 '12 at 21:40
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).

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
dav
  • 8,931
  • 15
  • 76
  • 140
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.

Uddhav Kambli
  • 448
  • 6
  • 11
  • 4
    Did you miss "PHP" in the question? There is a much better solution for Python already available: https://github.com/MrMinimal64/timezonefinder – hackel Feb 21 '18 at 16:03
-3

The Yahoo places API provides timezone information via reverse geolocation.

Check it out.

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

Jiho Kang
  • 2,482
  • 1
  • 28
  • 38
  • 1
    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. – tony gil Aug 13 '12 at 09:26
-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];

  }
Dziamid
  • 11,225
  • 12
  • 69
  • 104
  • 7
    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 May 08 '12 at 21:41
  • 1
    @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. – Dziamid May 17 '12 at 07:44
  • 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. – Shreeni Oct 07 '12 at 08:14