317 lines
6.9 KiB
JavaScript
317 lines
6.9 KiB
JavaScript
|
//! moment-timezone-utils.js
|
||
|
//! version : 0.5.14
|
||
|
//! Copyright (c) JS Foundation and other contributors
|
||
|
//! license : MIT
|
||
|
//! github.com/moment/moment-timezone
|
||
|
|
||
|
(function (root, factory) {
|
||
|
"use strict";
|
||
|
|
||
|
/*global define*/
|
||
|
if (typeof define === 'function' && define.amd) {
|
||
|
define(['moment'], factory); // AMD
|
||
|
} else if (typeof module === 'object' && module.exports) {
|
||
|
module.exports = factory(require('./')); // Node
|
||
|
} else {
|
||
|
factory(root.moment); // Browser
|
||
|
}
|
||
|
}(this, function (moment) {
|
||
|
"use strict";
|
||
|
|
||
|
if (!moment.tz) {
|
||
|
throw new Error("moment-timezone-utils.js must be loaded after moment-timezone.js");
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Pack Base 60
|
||
|
************************************/
|
||
|
|
||
|
var BASE60 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX',
|
||
|
EPSILON = 0.000001; // Used to fix floating point rounding errors
|
||
|
|
||
|
function packBase60Fraction(fraction, precision) {
|
||
|
var buffer = '.',
|
||
|
output = '',
|
||
|
current;
|
||
|
|
||
|
while (precision > 0) {
|
||
|
precision -= 1;
|
||
|
fraction *= 60;
|
||
|
current = Math.floor(fraction + EPSILON);
|
||
|
buffer += BASE60[current];
|
||
|
fraction -= current;
|
||
|
|
||
|
// Only add buffer to output once we have a non-zero value.
|
||
|
// This makes '.000' output '', and '.100' output '.1'
|
||
|
if (current) {
|
||
|
output += buffer;
|
||
|
buffer = '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
function packBase60(number, precision) {
|
||
|
var output = '',
|
||
|
absolute = Math.abs(number),
|
||
|
whole = Math.floor(absolute),
|
||
|
fraction = packBase60Fraction(absolute - whole, Math.min(~~precision, 10));
|
||
|
|
||
|
while (whole > 0) {
|
||
|
output = BASE60[whole % 60] + output;
|
||
|
whole = Math.floor(whole / 60);
|
||
|
}
|
||
|
|
||
|
if (number < 0) {
|
||
|
output = '-' + output;
|
||
|
}
|
||
|
|
||
|
if (output && fraction) {
|
||
|
return output + fraction;
|
||
|
}
|
||
|
|
||
|
if (!fraction && output === '-') {
|
||
|
return '0';
|
||
|
}
|
||
|
|
||
|
return output || fraction || '0';
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Pack
|
||
|
************************************/
|
||
|
|
||
|
function packUntils(untils) {
|
||
|
var out = [],
|
||
|
last = 0,
|
||
|
i;
|
||
|
|
||
|
for (i = 0; i < untils.length - 1; i++) {
|
||
|
out[i] = packBase60(Math.round((untils[i] - last) / 1000) / 60, 1);
|
||
|
last = untils[i];
|
||
|
}
|
||
|
|
||
|
return out.join(' ');
|
||
|
}
|
||
|
|
||
|
function packAbbrsAndOffsets(source) {
|
||
|
var index = 0,
|
||
|
abbrs = [],
|
||
|
offsets = [],
|
||
|
indices = [],
|
||
|
map = {},
|
||
|
i, key;
|
||
|
|
||
|
for (i = 0; i < source.abbrs.length; i++) {
|
||
|
key = source.abbrs[i] + '|' + source.offsets[i];
|
||
|
if (map[key] === undefined) {
|
||
|
map[key] = index;
|
||
|
abbrs[index] = source.abbrs[i];
|
||
|
offsets[index] = packBase60(Math.round(source.offsets[i] * 60) / 60, 1);
|
||
|
index++;
|
||
|
}
|
||
|
indices[i] = packBase60(map[key], 0);
|
||
|
}
|
||
|
|
||
|
return abbrs.join(' ') + '|' + offsets.join(' ') + '|' + indices.join('');
|
||
|
}
|
||
|
|
||
|
function packPopulation (number) {
|
||
|
if (!number) {
|
||
|
return '';
|
||
|
}
|
||
|
if (number < 1000) {
|
||
|
return '|' + number;
|
||
|
}
|
||
|
var exponent = String(number | 0).length - 2;
|
||
|
var precision = Math.round(number / Math.pow(10, exponent));
|
||
|
return '|' + precision + 'e' + exponent;
|
||
|
}
|
||
|
|
||
|
function validatePackData (source) {
|
||
|
if (!source.name) { throw new Error("Missing name"); }
|
||
|
if (!source.abbrs) { throw new Error("Missing abbrs"); }
|
||
|
if (!source.untils) { throw new Error("Missing untils"); }
|
||
|
if (!source.offsets) { throw new Error("Missing offsets"); }
|
||
|
if (
|
||
|
source.offsets.length !== source.untils.length ||
|
||
|
source.offsets.length !== source.abbrs.length
|
||
|
) {
|
||
|
throw new Error("Mismatched array lengths");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function pack (source) {
|
||
|
validatePackData(source);
|
||
|
return [
|
||
|
source.name,
|
||
|
packAbbrsAndOffsets(source),
|
||
|
packUntils(source.untils) + packPopulation(source.population)
|
||
|
].join('|');
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Create Links
|
||
|
************************************/
|
||
|
|
||
|
function arraysAreEqual(a, b) {
|
||
|
var i;
|
||
|
|
||
|
if (a.length !== b.length) { return false; }
|
||
|
|
||
|
for (i = 0; i < a.length; i++) {
|
||
|
if (a[i] !== b[i]) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function zonesAreEqual(a, b) {
|
||
|
return arraysAreEqual(a.offsets, b.offsets) && arraysAreEqual(a.abbrs, b.abbrs) && arraysAreEqual(a.untils, b.untils);
|
||
|
}
|
||
|
|
||
|
function findAndCreateLinks (input, output, links) {
|
||
|
var i, j, a, b, group, foundGroup, groups = [];
|
||
|
|
||
|
for (i = 0; i < input.length; i++) {
|
||
|
foundGroup = false;
|
||
|
a = input[i];
|
||
|
|
||
|
for (j = 0; j < groups.length; j++) {
|
||
|
group = groups[j];
|
||
|
b = group[0];
|
||
|
if (zonesAreEqual(a, b)) {
|
||
|
if (a.population > b.population) {
|
||
|
group.unshift(a);
|
||
|
} else {
|
||
|
group.push(a);
|
||
|
}
|
||
|
foundGroup = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!foundGroup) {
|
||
|
groups.push([a]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < groups.length; i++) {
|
||
|
group = groups[i];
|
||
|
output.push(group[0]);
|
||
|
for (j = 1; j < group.length; j++) {
|
||
|
links.push(group[0].name + '|' + group[j].name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createLinks (source) {
|
||
|
var zones = [],
|
||
|
links = [];
|
||
|
|
||
|
if (source.links) {
|
||
|
links = source.links.slice();
|
||
|
}
|
||
|
|
||
|
findAndCreateLinks(source.zones, zones, links);
|
||
|
|
||
|
return {
|
||
|
version : source.version,
|
||
|
zones : zones,
|
||
|
links : links.sort()
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Filter Years
|
||
|
************************************/
|
||
|
|
||
|
function findStartAndEndIndex (untils, start, end) {
|
||
|
var startI = 0,
|
||
|
endI = untils.length + 1,
|
||
|
untilYear,
|
||
|
i;
|
||
|
|
||
|
if (!end) {
|
||
|
end = start;
|
||
|
}
|
||
|
|
||
|
if (start > end) {
|
||
|
i = start;
|
||
|
start = end;
|
||
|
end = i;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < untils.length; i++) {
|
||
|
if (untils[i] == null) {
|
||
|
continue;
|
||
|
}
|
||
|
untilYear = new Date(untils[i]).getUTCFullYear();
|
||
|
if (untilYear < start) {
|
||
|
startI = i + 1;
|
||
|
}
|
||
|
if (untilYear > end) {
|
||
|
endI = Math.min(endI, i + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return [startI, endI];
|
||
|
}
|
||
|
|
||
|
function filterYears (source, start, end) {
|
||
|
var slice = Array.prototype.slice,
|
||
|
indices = findStartAndEndIndex(source.untils, start, end),
|
||
|
untils = slice.apply(source.untils, indices);
|
||
|
|
||
|
untils[untils.length - 1] = null;
|
||
|
|
||
|
return {
|
||
|
name : source.name,
|
||
|
abbrs : slice.apply(source.abbrs, indices),
|
||
|
untils : untils,
|
||
|
offsets : slice.apply(source.offsets, indices),
|
||
|
population : source.population
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Filter, Link, and Pack
|
||
|
************************************/
|
||
|
|
||
|
function filterLinkPack (input, start, end) {
|
||
|
var i,
|
||
|
inputZones = input.zones,
|
||
|
outputZones = [],
|
||
|
output;
|
||
|
|
||
|
for (i = 0; i < inputZones.length; i++) {
|
||
|
outputZones[i] = filterYears(inputZones[i], start, end);
|
||
|
}
|
||
|
|
||
|
output = createLinks({
|
||
|
zones : outputZones,
|
||
|
links : input.links.slice(),
|
||
|
version : input.version
|
||
|
});
|
||
|
|
||
|
for (i = 0; i < output.zones.length; i++) {
|
||
|
output.zones[i] = pack(output.zones[i]);
|
||
|
}
|
||
|
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
/************************************
|
||
|
Exports
|
||
|
************************************/
|
||
|
|
||
|
moment.tz.pack = pack;
|
||
|
moment.tz.packBase60 = packBase60;
|
||
|
moment.tz.createLinks = createLinks;
|
||
|
moment.tz.filterYears = filterYears;
|
||
|
moment.tz.filterLinkPack = filterLinkPack;
|
||
|
|
||
|
return moment;
|
||
|
}));
|