Skip to content

Commit

Permalink
Switch to local TZ lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
cpfair committed Nov 11, 2013
1 parent 9ff830e commit 79cb4f5
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 13 deletions.
1 change: 1 addition & 0 deletions tapiriik/database/__init__.py
Expand Up @@ -3,3 +3,4 @@
_connection = MongoClient(host=MONGO_HOST)
db = _connection["tapiriik"]
cachedb = _connection["tapiriik_cache"]
tzdb = _connection["tapiriik_tz"]
12 changes: 12 additions & 0 deletions tapiriik/database/tz.py
@@ -0,0 +1,12 @@
from tapiriik.database import tzdb
from bson.son import SON

def TZLookup(lat, lng):
pt = [lng, lat]
res = tzdb.boundaries.find_one({"Boundary": {"$geoIntersects": {"$geometry": {"type":"Point", "coordinates": pt}}}}, {"TZID": True})
if not res:
res = tzdb.boundaries.find_one({"Boundary": SON([("$near", {"$geometry": {"type": "Point", "coordinates": pt}}), ("$maxDistance", 200000)])}, {"TZID": True})
res = res["TZID"] if res else None
if not res or res == "uninhabited":
res = round(lng / 15)
return res
18 changes: 5 additions & 13 deletions tapiriik/services/interchange.py
@@ -1,9 +1,8 @@
from datetime import timedelta, datetime
from tapiriik.database import cachedb
import requests
from tapiriik.database.tz import TZLookup
import hashlib
import pytz
import warnings


class ActivityType: # taken from RK API docs. The text values have no meaning except for debugging
Expand Down Expand Up @@ -107,19 +106,12 @@ def CalculateTZ(self, loc=None):
break
if loc is None:
raise Exception("Can't find TZ without a waypoint with a location")

# I guess at some point it will be faster to perform a full lookup than digging through this table.
cachedTzData = cachedb.tz_cache.find_one({"Latitude": loc.Latitude, "Longitude": loc.Longitude})
if cachedTzData is None:
warnings.filterwarnings("ignore", "the 'strict' argument")
warnings.filterwarnings("ignore", "unclosed <socket")
resp = requests.get("http://api.geonames.org/timezoneJSON?username=tapiriik&radius=0.5&lat=" + str(loc.Latitude) + "&lng=" + str(loc.Longitude))
data = resp.json()
cachedTzData = {}
if "timezoneId" in data:
cachedTzData["TZ"] = data["timezoneId"]
else:
cachedTzData["TZ"] = data["rawOffset"]
cachedTzData["Latitude"] = loc.Latitude
cachedTzData["Longitude"] = loc.Longitude
res = TZLookup(loc.Latitude, loc.Longitude)
cachedTzData = {"TZ": res, "Latitude": loc.Latitude, "Longitude": loc.Longitude}
cachedb.tz_cache.insert(cachedTzData)

if type(cachedTzData["TZ"]) != str:
Expand Down
32 changes: 32 additions & 0 deletions tz_ingest.py
@@ -0,0 +1,32 @@
# This file isn't called in normal operation, just to update the TZ boundary DB.
# Should be called with `tz_world.*` files from http://efele.net/maps/tz/world/ in the working directory.
# Requires pyshp and shapely for py3k (from https://github.com/mwtoews/shapely/tree/py3)

import shapefile
from shapely.geometry import Polygon, mapping
import pymongo
from tapiriik.database import tzdb

print("Dropping boundaries collection")
tzdb.drop_collection("boundaries")

print("Setting up index")
tzdb.boundaries.ensure_index([("Boundary", pymongo.GEOSPHERE)])

print("Reading shapefile")
records = []
sf = shapefile.Reader("tz_world.shp")
shapeRecs = sf.shapeRecords()

ct = 0
total = len(shapeRecs)
for shape in shapeRecs:
tzid = shape.record[0]
print("%3d%% %s" % (round(ct * 100 / total), tzid))
ct += 1
polygon = Polygon(list(shape.shape.points))
if not polygon.is_valid:
polygon = polygon.buffer(0) # Resolves issues with most self-intersecting geometry
assert polygon.is_valid
record = {"TZID": tzid, "Boundary": mapping(polygon)}
tzdb.boundaries.insert(record) # Would be bulk insert, but that makes it a pain to debug geometry issues

0 comments on commit 79cb4f5

Please sign in to comment.