Determine timezone from latitude/longitude without using web services like Geonames.org

I had this problem a while back and did exactly what adam suggested:

  • Download the database of cities from geonames.org
  • convert it to a compact lat/lon -> timezone list
  • use an R-Tree implementation to efficiently lookup the nearest city (or rather, its timezone) to a given coordinate

IIRC it took less than 1 second to populate the R-Tree, and it could then perform thousands of lookups per second (both on a 5 year old PC).


How exact do your results have to be? If a rough estimate is enough, calculate the offset yourself:

offset = direction * longitude * 24 / 360

where direction is 1 for east, -1 for west, and longitude is in (-180,180)


I ran into this problem while working on another project and looked into it very deeply. I found all of the existing solutions to be lacking in major ways.

Downloading the GeoNames data and using some spatial index to look up the nearest point is definitely an option, and it will yield the correct result a lot of the time, but it can easily fail if a query point is on the wrong side of a time zone border from the nearest point in the database.

A more accurate method is to use a digital map of the time zones and to write code to find the polygon in that map that contains a given query point. Thankfully, there is an excellent map of the time zones of the world available at http://efele.net/maps/tz/world/ (not maintained anymore). To write an efficient query engine, you need to:

  • Parse the ESRI shapefile format into a useful internal representation.
  • Write point-in-polygon code to test whether a given query point is in a given polygon.
  • Write an efficient spatial index on top of the polygon data so that you don't need to check every polygon to find the containing one.
  • Handle queries that are not contained by any polygon (e.g., in the ocean). In such cases, you should "snap to" the nearest polygon up to a certain distance, and revert to the "natural" time zone (the one determined by longitude alone) in the open ocean. To do this, you will need code to compute the distance between a query point and a line segment of a polygon (this is non-trivial since latitude and longitude are a non-Euclidean coordinate system), and your spatial index will need to be able to return nearby polygons, not just potentially containing polygons.

Each of those are worthy of their own Stack Overflow question/answer page.

After concluding that none of the existing solutions out there met my needs, I wrote my own solution and made it available here:

http://askgeo.com

AskGeo uses a digital map and has a highly optimized spatial index that allows for running more than 10,000 queries per second on my computer in a single thread. And it is thread safe, so even higher throughput is certainly possible. This is a serious piece of code, and it took us a long time to develop, so we are offering it under a commercial license.

It is written in Java, so using it in PHP would involve using:

http://php-java-bridge.sourceforge.net/doc/how_it_works.php

We are also open to porting it for a bounty. For details on the pricing, and for detailed documentation, see http://askgeo.com.

I hope this is useful. It certainly was useful for the project I was working on.