timezonefinder is a python package for looking up the corresponding timezone for given coordinates on earth entirely offline.
Timezones internally are being represented by polygons and the timezone membership of a given point (= lat lng coordinate pair) is determined by a point in polygon (PIP) check.
In many cases an expensive PIP check can be avoided.
This package currently uses a precomputed timezone polygon index based on the geospatial hexagon index of the h3 library.
Among other tweaks this index makes
timezonefinder efficient (also check the performance chapter).
See the docstrings in the source code for further explanation.
Current data set in use: precompiled timezone-boundary-builder (WITH oceans, geoJSON)
In the data set the timezone polygons often include territorial waters -> they do NOT follow the shorelines.
This makes the results of
certain_timezone_at() less expressive:
from a timezone match one cannot distinguish whether a query point lies on land or in ocean.
Please note that timezone polygons might be overlapping (cf. e.g. timezone-boundary-builder/issue/105)
and that hence a query coordinate can actually match multiple time zones.
timezonefinder does currently NOT support such multiplicity and will always only return the first found match.
- package size: ~46 MB
- original data size: ~110 MB
ruby port: timezone_finder
Alternative python packages¶
Comparison to tzfpy¶
tzfpyis a Python binding of the Rust package
tzfpyhas no startup time
tzfpyuses simplified timezone polygons (data):
- this reduces the memory requirements
- this reduces the accuracy
- this increases the lookup speed
tzfpyuses hierarchical tree of rectangles to speed up the lookup but auto fall back to polygon data if cache miss
Comparison to pytzwhere¶
pytzwhere is parsing a 76MB .csv file (floats stored as strings!) completely into memory and computing shortcuts from this data on every startup.
This is time, memory and CPU consuming. Additionally calculating with floats is slow,
keeping those 4M+ floats in the RAM all the time is unnecessary and the precision of floats is not even needed in this case (s. detailed comparison and speed tests below).
In comparison most notably initialisation time and memory usage are significantly reduced.
pytzwhere is using up to 450MB of RAM (with
because it is parsing and keeping all the timezone polygons in the memory.
This uses unnecessary time/ computation/ memory and this was the reason I created this package in the first place.
This package uses at most 40MB (= encountered memory consumption of the python process) and has some more advantages:
- highly decreased memory usage
- highly reduced start up time
- usage of 32bit int (instead of 64+bit float) reduces computing time and memory consumption. The accuracy of 32bit int is still high enough. According to my calculations the worst accuracy is 1cm at the equator. This is far more precise than the discrete polygons in the data.
- the data is stored in memory friendly binary files (approx. 41MB in total, original data 120MB .json)
- data is only being read on demand (not completely read into memory if not needed)
- precomputed shortcuts are included to quickly look up which polygons have to be checked
get_geometry()enables querying timezones for their geometric shape (= multipolygon with holes)
- further speedup possible by the use of
numba(code JIT compilation)
- tz_where is still using the outdated tz_world data set
Tell me if and how your are using this package. This encourages me to develop and test it further.
Most certainly there is stuff I missed, things I could have optimized even further or explained more clearly, etc. I would be really glad to get some feedback.
If you encounter any bugs, have suggestions etc. do not hesitate to open an Issue or add a Pull Requests on Git. Please refer to the contribution guidelines
- Adam for adding organisational features to the project and for helping me with publishing and testing routines.
- ringsaturn for valuable feedback, sponsoring this project, creating the
tzfpypackage and adding the
- snowman2 for creating the conda-forge recipe.
- synapticarbors for fixing Numba import with py27.
- zedrdave for valuable feedback.
- Tyler Huntley for adding docstrings