forked from mapbox/timespace
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
103 lines (90 loc) · 3.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
var tiles = require('./lib/timezones.json');
var tilebelt = require('@mapbox/tilebelt');
var moment = require('moment-timezone');
var ss = require('simple-statistics');
var z = Object.keys(tiles)[0].split('/').map(Number)[2];
module.exports = {
getFuzzyLocalTimeFromPoint: getFuzzyLocalTimeFromPoint,
getFuzzyTimezoneFromTile: getFuzzyTimezoneFromTile,
getFuzzyTimezoneFromQuadkey: getFuzzyTimezoneFromQuadkey,
_getParent: _getParent, // expose for testing
_getChildren: _getChildren // expose for testing
};
/**
* Returns the local time at the point of interest.
* @param {Integer} timestamp a unix timestamp
* @param {Array} point a [lng, lat] point of interest
* @return {Object} a moment-timezone object
*/
function getFuzzyLocalTimeFromPoint(timestamp, point) {
var tile = tilebelt.pointToTile(point[0], point[1], z).join('/');
var locale = tiles[tile];
if (locale) return moment.tz(new Date(timestamp), locale);
else return undefined;
}
/**
* Retrieves the timezone of the tile of interest at z8-level accuracy.
* @param {Array} tile [x, y, z] coordinate of a tile
* @return {String} timezone for the tile
*/
function getFuzzyTimezoneFromTile(tile) {
if (tile[2] === z) {
var key = tile.join('/');
if (key in tiles) return tiles[key];
else throw new Error('tile not found');
} else if (tile[2] > z) {
// higher zoom level (9, 10, 11, ...)
key = _getParent(tile).join('/');
if (key in tiles) return tiles[key];
else throw new Error('tile not found');
} else {
// lower zoom level (..., 5, 6, 7)
var children = _getChildren(tile);
var votes = []; // list of timezone abbrevations
var abbrs = {}; // abbrevation to full name lookup table
children.forEach(function(child) {
key = child.join('/');
if (key in tiles) {
var tz = tiles[key]; // timezone name
// Need to use timezone abbreviation becuase e.g. America/Los_Angeles
// and America/Vancouver are the same. Use a time to determine the
// abbreviation, in case two similar tz have slightly different
// daylight savings schedule.
var abbr = moment.tz(Date.now(), tz)._z.abbrs[0];
votes.push(abbr);
abbrs[abbr] = tz;
}
});
if (votes.length > 1) return abbrs[ss.mode(votes)];
else throw new Error('tile not found');
}
}
/**
* Retrieves the timezone of the quadkey of interest at z8-level accuracy.
* @param {Array} quadkey a quadkey
* @return {String} timezone for the quadkey
*/
function getFuzzyTimezoneFromQuadkey(quadkey) {
var tile = tilebelt.quadkeyToTile(quadkey);
return getFuzzyTimezoneFromTile(tile);
}
/**
* [private function]
*/
function _getParent(tile) {
if (tile[2] < z) throw new Error('input tile zoom < ' + z);
if (tile[2] > z) return _getParent(tilebelt.getParent(tile));
else return tile;
}
/**
* [private function]
*/
function _getChildren(tile) {
if (tile[2] > z) throw new Error('input tile zoom > ' + z);
if (tile[2] === z) return [tile];
var children = tilebelt.getChildren(tile);
return _getChildren(children[0])
.concat(_getChildren(children[1]))
.concat(_getChildren(children[2]))
.concat(_getChildren(children[3]));
}