Goal: To take this: https://graph.facebook.com/105464892820215 And derive this: America/Los Angeles From which we can then derive UTC-0800 or UTC-0700, as appropriate under the daylight madness scheme in effect on the date of interest.
It seems oddly hard to figure out what timezone a given point in space is located in. Looking around, there are only a few APIs which provide this information (http://www.earthtools.org/webservices.htm#timezone and http://www.worldweatheronline.com/time-zone-api.aspx), and only a few datasets which seem to contain it; most of them are in serious GIS formats, and expect you to query them in some manual fashion using a proprietary GIS tool.
I'm not really interested in that; I want a piece of code I can just ask "what timezone is this in" and get an answer, without installing some huge piece of software I don't have a license to or worrying about rate limits from somebody's API. So I'm going to take a shapefile I found here (http://efele.net/maps/tz/world/) and see if we can turn it into something more easily queryable by Javascript, since I'm on a NodeJS kick recently.
Jim Vallandingham (that's quite a name) posted a writeup here (http://vallandingham.me/shapefile_to_geojson.html) about his experience converting to GeoJSON, so I'll try to use his experience as a guide.
nixon:~ matt$ brew install gdal
==> Installing gdal dependency: giflib
==> Downloading http://downloads.sourceforge.net/project/giflib/giflib%204.x/giflib-4.1.6/giflib-4.1.6.tar.bz2
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/giflib/4.1.6 --disable-debug
==> make install
/usr/local/Cellar/giflib/4.1.6: 37 files, 712K, built in 18 seconds
==> Installing gdal dependency: proj
==> Downloading http://download.osgeo.org/proj/proj-4.7.0.tar.gz
######################################################################## 100.0%
==> Downloading http://download.osgeo.org/proj/proj-datumgrid-1.5.zip
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/proj/4.7.0 --disable-debug
==> make install
/usr/local/Cellar/proj/4.7.0: 49 files, 5.6M, built in 28 seconds
==> Installing gdal dependency: geos
==> Downloading http://download.osgeo.org/geos/geos-3.3.1.tar.bz2
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/geos/3.3.1 --disable-debug
==> make install
/usr/local/Cellar/geos/3.3.1: 369 files, 8.4M, built in 2.8 minutes
==> Installing gdal
==> Downloading http://download.osgeo.org/gdal/gdal-1.8.1.tar.gz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/gdal/1.8.1 --disable-debug --with-local=/usr/local/Cellar/gdal/1.8.1 --with-threads --with-libtool --with-libtiff=internal --with-geotiff=internal --with-pcraster=internal --with-pcidsk=internal --with-bsb --with-grib --with-pam --with-libz
==> make
==> make install
==> python setup.py install_lib --install-dir=/usr/local/Cellar/gdal/1.8.1/lib/python
==> Caveats
This version of GDAL was built with Python support. In addition to providing
modules that makes GDAL functions available to Python scripts, the Python
binding provides ~18 additional command line tools. However, both the Python
bindings and the additional tools will be unusable unless the following
directory is added to the PYTHONPATH:
/usr/local/lib/python
==> Summary
/usr/local/Cellar/gdal/1.8.1: 168 files, 28M, built in 5.8 minutes
nixon:~ matt$
nixon:shapefile matt$ cd shapefile/
nixon:shapefile matt$ ls -l
total 71288
-rwxr-xr-x@ 1 matt staff 12004 Mar 29 15:33 index.html
-rwxr-xr-x@ 1 matt staff 859758 Mar 29 15:33 tz_world.dbf
-rwxr-xr-x@ 1 matt staff 136708 Mar 29 15:33 tz_world.png
-rwxr-xr-x@ 1 matt staff 257 Mar 29 15:33 tz_world.prj
-rwxr-xr-x@ 1 matt staff 35257332 Mar 29 15:33 tz_world.shp
-rwxr-xr-x@ 1 matt staff 221956 Mar 29 15:33 tz_world.shx
nixon:shapefile matt$ /usr/local/Cellar/gdal/1.8.1/bin/ogr2ogr -f geoJSON tz_world.json tz_world.shp
nixon:shapefile matt$ ls -l
total 188544
-rwxr-xr-x@ 1 matt staff 12004 Mar 29 15:33 index.html
-rwxr-xr-x@ 1 matt staff 859758 Mar 29 15:33 tz_world.dbf
-rw-r--r-- 1 matt staff 60032096 Mar 29 15:34 tz_world.json
-rwxr-xr-x@ 1 matt staff 136708 Mar 29 15:33 tz_world.png
-rwxr-xr-x@ 1 matt staff 257 Mar 29 15:33 tz_world.prj
-rwxr-xr-x@ 1 matt staff 35257332 Mar 29 15:33 tz_world.shp
-rwxr-xr-x@ 1 matt staff 221956 Mar 29 15:33 tz_world.shx
nixon:shapefile matt$
At this point I discovered that people had made Javascript libraries and tools to do this exact task. Good for them. Feel free to use one (like this: https://github.com/wavded/js-shapefile-to-geojson) if you want to do this process yourself. I'm only interested in one file, so this will be good enough for me.
At this point, we have a GeoJSON file which has a bunch of polygons for various timezones. After looking around for a tool which could use this, I found lots of tools which would map it for me (nice for some people, but not what I needed). I gave up, and decided that since it's just JSON, I could parse it myself. So I wrote this:
http://github.com/mattbornski/tzwhere
http://search.npmjs.org/#/tzwhere
It can tell you things about the timezone at (hopefully) any location on earth. Test cases only cover one, though, so if you find a hole, let me know. I used data from the source listed above, plus a few modules other people had written to interrogate geographic polygons and to manipulate dates in different timezones. In my opinion, the most function is the "dateAt" function, which (if I did things right) lets you get the Javascript Date object for a semantic time at a particular geographic location. So if you want to wish your friends in the White House a happy new year (automatically), try this:
var TwilioClient = require('twilio').Client;
var tzwhere = require('tzwhere');
setTimeout(function () {
var client = new TwilioClient(<sid>, <token≥, <hostname>);
var phone = client.getPhoneNumber(<phoneNumber>);
phone.setup(function () {
phone.sendSms('+12024561414','Happy new year!', null, function () {
return process.exit();
});
// Note that Javascript months are zero-indexed
}, tzwhere.dateAt(38.897663, -77.036562, 2013, 0, 1, 0, 0, 0, 0) - Date.now());
Probably best not to run that one until a little after Christmas, though...