Skip to content

Commit

Permalink
Create and search through user offsets.
Browse files Browse the repository at this point in the history
Allow guesses to ignore cached values.
  • Loading branch information
timrwood committed Oct 8, 2015
1 parent 2ab983b commit 2702c8a
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 41 deletions.
72 changes: 56 additions & 16 deletions moment-timezone.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
links = {},
names = {},
guesses = [],
cachedGuess,

momentVersion = moment.version.split('.'),
major = +momentVersion[0],
Expand Down Expand Up @@ -197,28 +198,70 @@
Current Timezone
************************************/

function OffsetAt(at) {
this.at = +at;
this.offset = at.getTimezoneOffset();
}

OffsetAt.prototype.matches = function (zone) {
return zone.offset(this.at) === this.offset;
};

function rebuildCurrentZone () {
var currentYear = new Date().getFullYear(),
jan = new Date(currentYear, 0, 1),
jul = new Date(currentYear, 6, 1),
janOffset = jan.getTimezoneOffset(),
julOffset = jul.getTimezoneOffset(),
zone, i;
function findChange(low, high) {
var mid, diff;

while ((diff = ((high.at - low.at) / 12e4 | 0) * 6e4)) {
mid = new OffsetAt(new Date(low.at + diff));
if (mid.offset === low.offset) {
low = mid;
} else {
high = mid;
}
}

return low;
}

function userOffsets() {
var startYear = new Date().getFullYear() - 2,
last = new OffsetAt(new Date(startYear, 0, 1)),
offsets = [last],
change, next, i;

for (i = 1; i < 48; i++) {
next = new OffsetAt(new Date(startYear, i, 1));
if (next.offset !== last.offset) {
change = findChange(last, next);
offsets.push(change);
offsets.push(new OffsetAt(new Date(change.at + 6e4)));
}
last = next;
}

return offsets;
}

function rebuildGuess () {
var offsets = userOffsets(),
zone, i, j, matched;

for (i = 0; i < guesses.length; i++) {
zone = getZone(guesses[i]);
if ((zone.offset(jan) === janOffset) && (zone.offset(jul) === julOffset)) {
matched = true;
for (j = 0; j < offsets.length; j++) {
matched = matched && offsets[j].matches(zone);
}
if (matched) {
return zone.name;
}
}
}

function guess () {
if (!tz._guess) {
tz._guess = rebuildCurrentZone();
function guess (ignoreCache) {
if (!cachedGuess || ignoreCache) {
cachedGuess = rebuildGuess();
}
return tz._guess;
return cachedGuess;
}

/************************************
Expand All @@ -242,9 +285,7 @@
normalized = normalizeName(name);
zones[normalized] = packed[i];
names[normalized] = name;
if (split[5]) {
guesses.push(name);
}
guesses.push(name);
}
}

Expand Down Expand Up @@ -361,7 +402,6 @@
tz.load = loadData;
tz.zone = getZone;
tz.zoneExists = zoneExists; // deprecated in 0.1.0
tz._guess = null;
tz.guess = guess;
tz.names = getNames;
tz.Zone = Zone;
Expand Down
37 changes: 12 additions & 25 deletions tests/moment-timezone/guess.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ var tz = require("../../").tz;

var getTimezoneOffset = Date.prototype.getTimezoneOffset;

function mockTimezoneOffset (jan, jul) {
function mockTimezoneOffset (zone) {
Date.prototype.getTimezoneOffset = function () {
var month = this.getMonth();
if (month > 3 && month < 9) {
return -jul;
}
return -jan;
return zone.offset(+this);
};
}

Expand All @@ -21,15 +17,12 @@ exports.guess = {
},

"different offsets should guess different timezones" : function (test) {
mockTimezoneOffset(0, 60);
tz._guess = null;
var london = tz.guess();
mockTimezoneOffset(-300, -240);
tz._guess = null;
var newYork = tz.guess();
mockTimezoneOffset(-480, -420);
tz._guess = null;
var losAngeles = tz.guess();
mockTimezoneOffset(tz.zone('Europe/London'));
var london = tz.guess(true);
mockTimezoneOffset(tz.zone('America/New_York'));
var newYork = tz.guess(true);
mockTimezoneOffset(tz.zone('America/Los_Angeles'));
var losAngeles = tz.guess(true);

test.ok(london);
test.ok(newYork);
Expand All @@ -41,18 +34,12 @@ exports.guess = {

"ensure each zone is represented" : function (test) {
var names = tz.names();
var year = new Date().getFullYear();
var jan = Date.UTC(year, 0, 1);
var jul = Date.UTC(year, 6, 1);
var zone, janOffset, julOffset;
var zone, i;

for (var i = 0; i < names.length; i++) {
for (i = 0; i < names.length; i++) {
zone = tz.zone(names[i]);
janOffset = zone.offset(jan);
julOffset = zone.offset(jul);
mockTimezoneOffset(-janOffset, -julOffset);
tz._guess = null;
test.ok(tz.guess(), "Should have a guess for " + zone.name + " (jan " + janOffset + " jul " + julOffset + ")");
mockTimezoneOffset(zone);
test.ok(tz.guess(true), "Should have a guess for " + zone.name + ")");
}
test.done();
}
Expand Down

0 comments on commit 2702c8a

Please sign in to comment.