233aeeb12f
fixed bug of duplicate penalties fixed showing timeline date for non events refresh player count on server overview fix refresh privileged users on map load fix 1h showing on tempban if manually specified
606 lines
14 KiB
JavaScript
606 lines
14 KiB
JavaScript
//! moment-timezone.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('moment')); // Node
|
|
} else {
|
|
factory(root.moment); // Browser
|
|
}
|
|
}(this, function (moment) {
|
|
"use strict";
|
|
|
|
// Do not load moment-timezone a second time.
|
|
// if (moment.tz !== undefined) {
|
|
// logError('Moment Timezone ' + moment.tz.version + ' was already loaded ' + (moment.tz.dataVersion ? 'with data from ' : 'without any data') + moment.tz.dataVersion);
|
|
// return moment;
|
|
// }
|
|
|
|
var VERSION = "0.5.14",
|
|
zones = {},
|
|
links = {},
|
|
names = {},
|
|
guesses = {},
|
|
cachedGuess,
|
|
|
|
momentVersion = moment.version.split('.'),
|
|
major = +momentVersion[0],
|
|
minor = +momentVersion[1];
|
|
|
|
// Moment.js version check
|
|
if (major < 2 || (major === 2 && minor < 6)) {
|
|
logError('Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js ' + moment.version + '. See momentjs.com');
|
|
}
|
|
|
|
/************************************
|
|
Unpacking
|
|
************************************/
|
|
|
|
function charCodeToInt(charCode) {
|
|
if (charCode > 96) {
|
|
return charCode - 87;
|
|
} else if (charCode > 64) {
|
|
return charCode - 29;
|
|
}
|
|
return charCode - 48;
|
|
}
|
|
|
|
function unpackBase60(string) {
|
|
var i = 0,
|
|
parts = string.split('.'),
|
|
whole = parts[0],
|
|
fractional = parts[1] || '',
|
|
multiplier = 1,
|
|
num,
|
|
out = 0,
|
|
sign = 1;
|
|
|
|
// handle negative numbers
|
|
if (string.charCodeAt(0) === 45) {
|
|
i = 1;
|
|
sign = -1;
|
|
}
|
|
|
|
// handle digits before the decimal
|
|
for (i; i < whole.length; i++) {
|
|
num = charCodeToInt(whole.charCodeAt(i));
|
|
out = 60 * out + num;
|
|
}
|
|
|
|
// handle digits after the decimal
|
|
for (i = 0; i < fractional.length; i++) {
|
|
multiplier = multiplier / 60;
|
|
num = charCodeToInt(fractional.charCodeAt(i));
|
|
out += num * multiplier;
|
|
}
|
|
|
|
return out * sign;
|
|
}
|
|
|
|
function arrayToInt (array) {
|
|
for (var i = 0; i < array.length; i++) {
|
|
array[i] = unpackBase60(array[i]);
|
|
}
|
|
}
|
|
|
|
function intToUntil (array, length) {
|
|
for (var i = 0; i < length; i++) {
|
|
array[i] = Math.round((array[i - 1] || 0) + (array[i] * 60000)); // minutes to milliseconds
|
|
}
|
|
|
|
array[length - 1] = Infinity;
|
|
}
|
|
|
|
function mapIndices (source, indices) {
|
|
var out = [], i;
|
|
|
|
for (i = 0; i < indices.length; i++) {
|
|
out[i] = source[indices[i]];
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
function unpack (string) {
|
|
var data = string.split('|'),
|
|
offsets = data[2].split(' '),
|
|
indices = data[3].split(''),
|
|
untils = data[4].split(' ');
|
|
|
|
arrayToInt(offsets);
|
|
arrayToInt(indices);
|
|
arrayToInt(untils);
|
|
|
|
intToUntil(untils, indices.length);
|
|
|
|
return {
|
|
name : data[0],
|
|
abbrs : mapIndices(data[1].split(' '), indices),
|
|
offsets : mapIndices(offsets, indices),
|
|
untils : untils,
|
|
population : data[5] | 0
|
|
};
|
|
}
|
|
|
|
/************************************
|
|
Zone object
|
|
************************************/
|
|
|
|
function Zone (packedString) {
|
|
if (packedString) {
|
|
this._set(unpack(packedString));
|
|
}
|
|
}
|
|
|
|
Zone.prototype = {
|
|
_set : function (unpacked) {
|
|
this.name = unpacked.name;
|
|
this.abbrs = unpacked.abbrs;
|
|
this.untils = unpacked.untils;
|
|
this.offsets = unpacked.offsets;
|
|
this.population = unpacked.population;
|
|
},
|
|
|
|
_index : function (timestamp) {
|
|
var target = +timestamp,
|
|
untils = this.untils,
|
|
i;
|
|
|
|
for (i = 0; i < untils.length; i++) {
|
|
if (target < untils[i]) {
|
|
return i;
|
|
}
|
|
}
|
|
},
|
|
|
|
parse : function (timestamp) {
|
|
var target = +timestamp,
|
|
offsets = this.offsets,
|
|
untils = this.untils,
|
|
max = untils.length - 1,
|
|
offset, offsetNext, offsetPrev, i;
|
|
|
|
for (i = 0; i < max; i++) {
|
|
offset = offsets[i];
|
|
offsetNext = offsets[i + 1];
|
|
offsetPrev = offsets[i ? i - 1 : i];
|
|
|
|
if (offset < offsetNext && tz.moveAmbiguousForward) {
|
|
offset = offsetNext;
|
|
} else if (offset > offsetPrev && tz.moveInvalidForward) {
|
|
offset = offsetPrev;
|
|
}
|
|
|
|
if (target < untils[i] - (offset * 60000)) {
|
|
return offsets[i];
|
|
}
|
|
}
|
|
|
|
return offsets[max];
|
|
},
|
|
|
|
abbr : function (mom) {
|
|
return this.abbrs[this._index(mom)];
|
|
},
|
|
|
|
offset : function (mom) {
|
|
logError("zone.offset has been deprecated in favor of zone.utcOffset");
|
|
return this.offsets[this._index(mom)];
|
|
},
|
|
|
|
utcOffset : function (mom) {
|
|
return this.offsets[this._index(mom)];
|
|
}
|
|
};
|
|
|
|
/************************************
|
|
Current Timezone
|
|
************************************/
|
|
|
|
function OffsetAt(at) {
|
|
var timeString = at.toTimeString();
|
|
var abbr = timeString.match(/\([a-z ]+\)/i);
|
|
if (abbr && abbr[0]) {
|
|
// 17:56:31 GMT-0600 (CST)
|
|
// 17:56:31 GMT-0600 (Central Standard Time)
|
|
abbr = abbr[0].match(/[A-Z]/g);
|
|
abbr = abbr ? abbr.join('') : undefined;
|
|
} else {
|
|
// 17:56:31 CST
|
|
// 17:56:31 GMT+0800 (台北標準時間)
|
|
abbr = timeString.match(/[A-Z]{3,5}/g);
|
|
abbr = abbr ? abbr[0] : undefined;
|
|
}
|
|
|
|
if (abbr === 'GMT') {
|
|
abbr = undefined;
|
|
}
|
|
|
|
this.at = +at;
|
|
this.abbr = abbr;
|
|
this.offset = at.getTimezoneOffset();
|
|
}
|
|
|
|
function ZoneScore(zone) {
|
|
this.zone = zone;
|
|
this.offsetScore = 0;
|
|
this.abbrScore = 0;
|
|
}
|
|
|
|
ZoneScore.prototype.scoreOffsetAt = function (offsetAt) {
|
|
this.offsetScore += Math.abs(this.zone.utcOffset(offsetAt.at) - offsetAt.offset);
|
|
if (this.zone.abbr(offsetAt.at).replace(/[^A-Z]/g, '') !== offsetAt.abbr) {
|
|
this.abbrScore++;
|
|
}
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
offsets.push(new OffsetAt(new Date(startYear + i, 0, 1)));
|
|
offsets.push(new OffsetAt(new Date(startYear + i, 6, 1)));
|
|
}
|
|
|
|
return offsets;
|
|
}
|
|
|
|
function sortZoneScores (a, b) {
|
|
if (a.offsetScore !== b.offsetScore) {
|
|
return a.offsetScore - b.offsetScore;
|
|
}
|
|
if (a.abbrScore !== b.abbrScore) {
|
|
return a.abbrScore - b.abbrScore;
|
|
}
|
|
return b.zone.population - a.zone.population;
|
|
}
|
|
|
|
function addToGuesses (name, offsets) {
|
|
var i, offset;
|
|
arrayToInt(offsets);
|
|
for (i = 0; i < offsets.length; i++) {
|
|
offset = offsets[i];
|
|
guesses[offset] = guesses[offset] || {};
|
|
guesses[offset][name] = true;
|
|
}
|
|
}
|
|
|
|
function guessesForUserOffsets (offsets) {
|
|
var offsetsLength = offsets.length,
|
|
filteredGuesses = {},
|
|
out = [],
|
|
i, j, guessesOffset;
|
|
|
|
for (i = 0; i < offsetsLength; i++) {
|
|
guessesOffset = guesses[offsets[i].offset] || {};
|
|
for (j in guessesOffset) {
|
|
if (guessesOffset.hasOwnProperty(j)) {
|
|
filteredGuesses[j] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i in filteredGuesses) {
|
|
if (filteredGuesses.hasOwnProperty(i)) {
|
|
out.push(names[i]);
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
function rebuildGuess () {
|
|
|
|
// use Intl API when available and returning valid time zone
|
|
try {
|
|
var intlName = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
if (intlName && intlName.length > 3) {
|
|
var name = names[normalizeName(intlName)];
|
|
if (name) {
|
|
return name;
|
|
}
|
|
logError("Moment Timezone found " + intlName + " from the Intl api, but did not have that data loaded.");
|
|
}
|
|
} catch (e) {
|
|
// Intl unavailable, fall back to manual guessing.
|
|
}
|
|
|
|
var offsets = userOffsets(),
|
|
offsetsLength = offsets.length,
|
|
guesses = guessesForUserOffsets(offsets),
|
|
zoneScores = [],
|
|
zoneScore, i, j;
|
|
|
|
for (i = 0; i < guesses.length; i++) {
|
|
zoneScore = new ZoneScore(getZone(guesses[i]), offsetsLength);
|
|
for (j = 0; j < offsetsLength; j++) {
|
|
zoneScore.scoreOffsetAt(offsets[j]);
|
|
}
|
|
zoneScores.push(zoneScore);
|
|
}
|
|
|
|
zoneScores.sort(sortZoneScores);
|
|
|
|
return zoneScores.length > 0 ? zoneScores[0].zone.name : undefined;
|
|
}
|
|
|
|
function guess (ignoreCache) {
|
|
if (!cachedGuess || ignoreCache) {
|
|
cachedGuess = rebuildGuess();
|
|
}
|
|
return cachedGuess;
|
|
}
|
|
|
|
/************************************
|
|
Global Methods
|
|
************************************/
|
|
|
|
function normalizeName (name) {
|
|
return (name || '').toLowerCase().replace(/\//g, '_');
|
|
}
|
|
|
|
function addZone (packed) {
|
|
var i, name, split, normalized;
|
|
|
|
if (typeof packed === "string") {
|
|
packed = [packed];
|
|
}
|
|
|
|
for (i = 0; i < packed.length; i++) {
|
|
split = packed[i].split('|');
|
|
name = split[0];
|
|
normalized = normalizeName(name);
|
|
zones[normalized] = packed[i];
|
|
names[normalized] = name;
|
|
addToGuesses(normalized, split[2].split(' '));
|
|
}
|
|
}
|
|
|
|
function getZone (name, caller) {
|
|
name = normalizeName(name);
|
|
|
|
var zone = zones[name];
|
|
var link;
|
|
|
|
if (zone instanceof Zone) {
|
|
return zone;
|
|
}
|
|
|
|
if (typeof zone === 'string') {
|
|
zone = new Zone(zone);
|
|
zones[name] = zone;
|
|
return zone;
|
|
}
|
|
|
|
// Pass getZone to prevent recursion more than 1 level deep
|
|
if (links[name] && caller !== getZone && (link = getZone(links[name], getZone))) {
|
|
zone = zones[name] = new Zone();
|
|
zone._set(link);
|
|
zone.name = names[name];
|
|
return zone;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function getNames () {
|
|
var i, out = [];
|
|
|
|
for (i in names) {
|
|
if (names.hasOwnProperty(i) && (zones[i] || zones[links[i]]) && names[i]) {
|
|
out.push(names[i]);
|
|
}
|
|
}
|
|
|
|
return out.sort();
|
|
}
|
|
|
|
function addLink (aliases) {
|
|
var i, alias, normal0, normal1;
|
|
|
|
if (typeof aliases === "string") {
|
|
aliases = [aliases];
|
|
}
|
|
|
|
for (i = 0; i < aliases.length; i++) {
|
|
alias = aliases[i].split('|');
|
|
|
|
normal0 = normalizeName(alias[0]);
|
|
normal1 = normalizeName(alias[1]);
|
|
|
|
links[normal0] = normal1;
|
|
names[normal0] = alias[0];
|
|
|
|
links[normal1] = normal0;
|
|
names[normal1] = alias[1];
|
|
}
|
|
}
|
|
|
|
function loadData (data) {
|
|
addZone(data.zones);
|
|
addLink(data.links);
|
|
tz.dataVersion = data.version;
|
|
}
|
|
|
|
function zoneExists (name) {
|
|
if (!zoneExists.didShowError) {
|
|
zoneExists.didShowError = true;
|
|
logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')");
|
|
}
|
|
return !!getZone(name);
|
|
}
|
|
|
|
function needsOffset (m) {
|
|
var isUnixTimestamp = (m._f === 'X' || m._f === 'x');
|
|
return !!(m._a && (m._tzm === undefined) && !isUnixTimestamp);
|
|
}
|
|
|
|
function logError (message) {
|
|
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
|
console.error(message);
|
|
}
|
|
}
|
|
|
|
/************************************
|
|
moment.tz namespace
|
|
************************************/
|
|
|
|
function tz (input) {
|
|
var args = Array.prototype.slice.call(arguments, 0, -1),
|
|
name = arguments[arguments.length - 1],
|
|
zone = getZone(name),
|
|
out = moment.utc.apply(null, args);
|
|
|
|
if (zone && !moment.isMoment(input) && needsOffset(out)) {
|
|
out.add(zone.parse(out), 'minutes');
|
|
}
|
|
|
|
out.tz(name);
|
|
|
|
return out;
|
|
}
|
|
|
|
tz.version = VERSION;
|
|
tz.dataVersion = '';
|
|
tz._zones = zones;
|
|
tz._links = links;
|
|
tz._names = names;
|
|
tz.add = addZone;
|
|
tz.link = addLink;
|
|
tz.load = loadData;
|
|
tz.zone = getZone;
|
|
tz.zoneExists = zoneExists; // deprecated in 0.1.0
|
|
tz.guess = guess;
|
|
tz.names = getNames;
|
|
tz.Zone = Zone;
|
|
tz.unpack = unpack;
|
|
tz.unpackBase60 = unpackBase60;
|
|
tz.needsOffset = needsOffset;
|
|
tz.moveInvalidForward = true;
|
|
tz.moveAmbiguousForward = false;
|
|
|
|
/************************************
|
|
Interface with Moment.js
|
|
************************************/
|
|
|
|
var fn = moment.fn;
|
|
|
|
moment.tz = tz;
|
|
|
|
moment.defaultZone = null;
|
|
|
|
moment.updateOffset = function (mom, keepTime) {
|
|
var zone = moment.defaultZone,
|
|
offset;
|
|
|
|
if (mom._z === undefined) {
|
|
if (zone && needsOffset(mom) && !mom._isUTC) {
|
|
mom._d = moment.utc(mom._a)._d;
|
|
mom.utc().add(zone.parse(mom), 'minutes');
|
|
}
|
|
mom._z = zone;
|
|
}
|
|
if (mom._z) {
|
|
offset = mom._z.utcOffset(mom);
|
|
if (Math.abs(offset) < 16) {
|
|
offset = offset / 60;
|
|
}
|
|
if (mom.utcOffset !== undefined) {
|
|
mom.utcOffset(-offset, keepTime);
|
|
} else {
|
|
mom.zone(offset, keepTime);
|
|
}
|
|
}
|
|
};
|
|
|
|
fn.tz = function (name, keepTime) {
|
|
if (name) {
|
|
this._z = getZone(name);
|
|
if (this._z) {
|
|
moment.updateOffset(this, keepTime);
|
|
} else {
|
|
logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/.");
|
|
}
|
|
return this;
|
|
}
|
|
if (this._z) { return this._z.name; }
|
|
};
|
|
|
|
function abbrWrap (old) {
|
|
return function () {
|
|
if (this._z) { return this._z.abbr(this); }
|
|
return old.call(this);
|
|
};
|
|
}
|
|
|
|
function resetZoneWrap (old) {
|
|
return function () {
|
|
this._z = null;
|
|
return old.apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
fn.zoneName = abbrWrap(fn.zoneName);
|
|
fn.zoneAbbr = abbrWrap(fn.zoneAbbr);
|
|
fn.utc = resetZoneWrap(fn.utc);
|
|
|
|
moment.tz.setDefault = function(name) {
|
|
if (major < 2 || (major === 2 && minor < 9)) {
|
|
logError('Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js ' + moment.version + '.');
|
|
}
|
|
moment.defaultZone = name ? getZone(name) : null;
|
|
return moment;
|
|
};
|
|
|
|
// Cloning a moment should include the _z property.
|
|
var momentProperties = moment.momentProperties;
|
|
if (Object.prototype.toString.call(momentProperties) === '[object Array]') {
|
|
// moment 2.8.1+
|
|
momentProperties.push('_z');
|
|
momentProperties.push('_a');
|
|
} else if (momentProperties) {
|
|
// moment 2.7.0
|
|
momentProperties._z = null;
|
|
}
|
|
|
|
// INJECT DATA
|
|
|
|
return moment;
|
|
}));
|