340 lines
7.6 KiB
JavaScript
340 lines
7.6 KiB
JavaScript
//! moment-timezone-utils.js
|
|
//! version : 0.5.34
|
|
//! Copyright (c) JS Foundation and other contributors
|
|
//! license : MIT
|
|
//! github.com/moment/moment-timezone
|
|
|
|
(function (root, factory) {
|
|
"use strict";
|
|
|
|
/*global define*/
|
|
if (typeof module === 'object' && module.exports) {
|
|
module.exports = factory(require('./')); // Node
|
|
} else if (typeof define === 'function' && define.amd) {
|
|
define(['moment'], factory); // AMD
|
|
} 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 packCountries (countries) {
|
|
if (!countries) {
|
|
return '';
|
|
}
|
|
return countries.join(' ');
|
|
}
|
|
|
|
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, // 0 - timezone name
|
|
packAbbrsAndOffsets(source), // 1 - abbrs, 2 - offsets, 3 - indices
|
|
packUntils(source.untils), // 4 - untils
|
|
packPopulation(source.population) // 5 - population
|
|
].join('|');
|
|
}
|
|
|
|
function packCountry (source) {
|
|
return [
|
|
source.name,
|
|
source.zones.join(' '),
|
|
].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, groupLeaders) {
|
|
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 if (a.population === b.population && groupLeaders && groupLeaders[a.name]) {
|
|
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, groupLeaders) {
|
|
var zones = [],
|
|
links = [];
|
|
|
|
if (source.links) {
|
|
links = source.links.slice();
|
|
}
|
|
|
|
findAndCreateLinks(source.zones, zones, links, groupLeaders);
|
|
|
|
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,
|
|
countries : source.countries
|
|
};
|
|
}
|
|
|
|
/************************************
|
|
Filter, Link, and Pack
|
|
************************************/
|
|
|
|
function filterLinkPack (input, start, end, groupLeaders) {
|
|
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
|
|
}, groupLeaders);
|
|
|
|
for (i = 0; i < output.zones.length; i++) {
|
|
output.zones[i] = pack(output.zones[i]);
|
|
}
|
|
|
|
output.countries = input.countries ? input.countries.map(function (unpacked) {
|
|
return packCountry(unpacked);
|
|
}) : [];
|
|
|
|
return output;
|
|
}
|
|
|
|
/************************************
|
|
Exports
|
|
************************************/
|
|
|
|
moment.tz.pack = pack;
|
|
moment.tz.packBase60 = packBase60;
|
|
moment.tz.createLinks = createLinks;
|
|
moment.tz.filterYears = filterYears;
|
|
moment.tz.filterLinkPack = filterLinkPack;
|
|
moment.tz.packCountry = packCountry;
|
|
|
|
return moment;
|
|
}));
|