diff --git a/README.md b/README.md index c1452f30..d5ccc3fd 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ The most up-to-date and accurate node.js geographical timezone lookup package. ```javascript var geoTz = require('geo-tz') + geoTz.preCache() // optionally load all features into memory geoTz(47.650499, -122.350070) // ['America/Los_Angeles'] geoTz(43.839319, 87.526148) // ['Asia/Shanghai', 'Asia/Urumqi'] ``` @@ -26,7 +27,11 @@ Returns the timezone names found at `lat`, `lon`. The timezone names will be th This library does an exact geographic lookup which has tradeoffs. It is perhaps a little bit slower that other libraries, has a larger installation size on disk and cannot be used in the browser. However, the results are more accurate than other libraries that compromise by approximating the lookup of the data. -The data is indexed for fast analysis with automatic caching (with time expiration) of subregions of geographic data for when a precise lookup is needed. +The data is indexed for fast analysis with automatic caching with time expiration (or optional an unexpiring cache of the whole world) of subregions of geographic data for when a precise lookup is needed. + +### geoTz.preCache() + +Loads all geographic features into memory in an unexpiring cache. This has tradeoffs. More memory will be consumed and it will take a little longer before the program is ready to start looking up features, but future lookups will be a lot faster - especially for areas which haven't had a lookup in a while. ## An Important Note About Maintenance diff --git a/lib/find.js b/lib/find.js index 938b53de..2feafe9f 100644 --- a/lib/find.js +++ b/lib/find.js @@ -9,7 +9,30 @@ var point = require('@turf/helpers').point var tzData = require('../data/index.json') -const featureCache = new Cache() +let featureCache = new Cache() + +/** + * A function that will load all features into an unexpiring cache + */ +var preCache = function () { + const _eternalCache = {} + featureCache = { + get: (quadPos) => _eternalCache[quadPos] + } + + // shoutout to github user @magwo for an initial version of this recursive function + var preloadFeaturesRecursive = function (curTzData, quadPos) { + if (curTzData === 'f') { + var geoJson = loadFeatures(quadPos) + _eternalCache[quadPos] = geoJson + } else if (typeof curTzData === 'object') { + Object.getOwnPropertyNames(curTzData).forEach(function (value) { + preloadFeaturesRecursive(curTzData[value], quadPos + value) + }) + } + } + preloadFeaturesRecursive(tzData.lookup, '') +} var loadFeatures = function (quadPos) { // exact boundaries saved in file @@ -169,3 +192,4 @@ var getTimezone = function (lat, lon) { } module.exports = getTimezone +module.exports.preCache = preCache diff --git a/tests/find.test.js b/tests/find.test.js index 9eb8e561..8865d9f7 100644 --- a/tests/find.test.js +++ b/tests/find.test.js @@ -51,7 +51,7 @@ describe('find tests', function () { var europeBottomRight = [39.8602076, 34.9127951] var count = 2000 - it('should find timezone of ' + count + ' random european positions', function () { + var findRandomPositions = function () { var timingStr = 'find tz of ' + count + ' random european positions' console.time(timingStr) for (var i = 0; i < count; i++) { @@ -61,6 +61,19 @@ describe('find tests', function () { ) } console.timeEnd(timingStr) - }) + } + + it( + 'should find timezone of ' + count + ' random european positions with on-demand caching', + findRandomPositions + ) + + it( + 'should find timezone of ' + count + ' random european positions with precache', + function () { + geoTz.preCache() + findRandomPositions() + } + ) }) })