WhereTZ: timezone lookup
WhereTZ is elixir version of Ruby gem for lookup of timezone by georgraphic coordinates.
https://github.com/zverok/wheretz
Features:
- no calls to external services, works without Internet connection;
- Timezone result is %Timex.TimezoneInfo
Usage
Add to project from hex.pm
def deps do
[
{:wheretz, "~> 0.1.1"},
]
end
or from github
def deps do
[
{:wheretz, git: "git@github.com:UA3MQJ/wheretz.git", tag: "v0.1.1"},
]
end
usage
iex(1)> WhereTZ.get(50.004444, 36.231389)
#<TimezoneInfo(Europe/Kiev - EET (+02:00:00))>
iex(2)> WhereTZ.lookup(50.004444, 36.231389)
"Europe/Kiev"
How it works
- Latest version of timezone-boundary-builder dataset is converted into ~400
data/*.geojson
files; - Each of those files corresponds to one timezone; filename contains timezone name and bounding box (min and max latitude and longitude);
- On each lookup
WhereTZ
first checks provided coordinates by bounding boxes, and if only one bbox (extracted from filename) corresponds to them, returns timezone name immediately; - If there's several intersecting bounding boxes,
WhereTZ
reads only relevant timezone files (which are not very large) and checks which polygon actually contains the point.
Known problems
- On "bounding box only" check, some points deeply in sea (and actually belonging to no timezone polygon) can be wrongly guessed as belonging to some timezone;
Рецепты
Moscow
WhereTZ.lookup(55.75, 37.616667)
point = %Geo.Point{ coordinates: {55.75, 37.616667}}
{:ok, file} = File.open("./priv/data/Europe-Moscow__26.4402__69.9572__41.1851__82.0586.geojson", [:read])
json1 = IO.binread(file, :all)
File.close(file)
data1 = Jason.decode!(json) |> Geo.JSON.decode!()
paris
WhereTZ.lookup(43.6605555555556, 7.2175)
point = %Geo.Point{ coordinates: {43.6605555555556, 7.2175}}
Kharkiv
WhereTZ.lookup(50.004444, 36.231389)
{:ok, file} = File.open("./priv/data/Europe-Kiev__22.6408__40.2276__45.0532__52.3791.geojson", [:read])
json1 = IO.binread(file, :all)
File.close(file)
{:ok, file} = File.open("./priv/data/Europe-Moscow__26.4402__69.9572__41.1851__82.0586.geojson", [:read])
json2 = IO.binread(file, :all)
File.close(file)
data1 = Jason.decode!(json1) |> Geo.JSON.decode!()
data2 = Jason.decode!(json2) |> Geo.JSON.decode!()
point = %Geo.Point{ coordinates: {36.231389, 50.004444}}
WhereTZ.lookup(50.28337, -107.80135)
point = %Geo.Point{ coordinates: {-107.80135, 50.28337}}
{:ok, file} = File.open("./priv/data/America-Regina__-110.0064__-101.3619__48.9988__59.9998.geojson", [:read])
json1 = IO.binread(file, :all)
File.close(file)
{:ok, file} = File.open("./priv/data/America-Swift_Current__-107.8381__-107.7563__50.2588__50.3246.geojson", [:read])
json2 = IO.binread(file, :all)
File.close(file)
data1 = Jason.decode!(json1) |> Geo.JSON.decode!()
data2 = Jason.decode!(json2) |> Geo.JSON.decode!()
lat = 50.004444
lng = 36.231389
where = :ets.fun2ms(fn({:geo, zone_name, minx, maxx, miny, maxy, geo_object}) when lng>=minx and lng<=maxx and lat>=miny and lat<=maxy -> zone_name end)
:mnesia.transaction(fn() -> :mnesia.select(:geo, where) end)