PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/moment-timezone/moment-timezone.js

https://bitbucket.org/gilae/secretarybot
JavaScript | 605 lines | 455 code | 106 blank | 44 comment | 101 complexity | d62cc9b884324101e4ea770765182331 MD5 | raw file
Possible License(s): 0BSD, MIT, Apache-2.0, Unlicense
  1. //! moment-timezone.js
  2. //! version : 0.5.16
  3. //! Copyright (c) JS Foundation and other contributors
  4. //! license : MIT
  5. //! github.com/moment/moment-timezone
  6. (function (root, factory) {
  7. "use strict";
  8. /*global define*/
  9. if (typeof define === 'function' && define.amd) {
  10. define(['moment'], factory); // AMD
  11. } else if (typeof module === 'object' && module.exports) {
  12. module.exports = factory(require('moment')); // Node
  13. } else {
  14. factory(root.moment); // Browser
  15. }
  16. }(this, function (moment) {
  17. "use strict";
  18. // Do not load moment-timezone a second time.
  19. // if (moment.tz !== undefined) {
  20. // logError('Moment Timezone ' + moment.tz.version + ' was already loaded ' + (moment.tz.dataVersion ? 'with data from ' : 'without any data') + moment.tz.dataVersion);
  21. // return moment;
  22. // }
  23. var VERSION = "0.5.16",
  24. zones = {},
  25. links = {},
  26. names = {},
  27. guesses = {},
  28. cachedGuess,
  29. momentVersion = moment.version.split('.'),
  30. major = +momentVersion[0],
  31. minor = +momentVersion[1];
  32. // Moment.js version check
  33. if (major < 2 || (major === 2 && minor < 6)) {
  34. logError('Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js ' + moment.version + '. See momentjs.com');
  35. }
  36. /************************************
  37. Unpacking
  38. ************************************/
  39. function charCodeToInt(charCode) {
  40. if (charCode > 96) {
  41. return charCode - 87;
  42. } else if (charCode > 64) {
  43. return charCode - 29;
  44. }
  45. return charCode - 48;
  46. }
  47. function unpackBase60(string) {
  48. var i = 0,
  49. parts = string.split('.'),
  50. whole = parts[0],
  51. fractional = parts[1] || '',
  52. multiplier = 1,
  53. num,
  54. out = 0,
  55. sign = 1;
  56. // handle negative numbers
  57. if (string.charCodeAt(0) === 45) {
  58. i = 1;
  59. sign = -1;
  60. }
  61. // handle digits before the decimal
  62. for (i; i < whole.length; i++) {
  63. num = charCodeToInt(whole.charCodeAt(i));
  64. out = 60 * out + num;
  65. }
  66. // handle digits after the decimal
  67. for (i = 0; i < fractional.length; i++) {
  68. multiplier = multiplier / 60;
  69. num = charCodeToInt(fractional.charCodeAt(i));
  70. out += num * multiplier;
  71. }
  72. return out * sign;
  73. }
  74. function arrayToInt (array) {
  75. for (var i = 0; i < array.length; i++) {
  76. array[i] = unpackBase60(array[i]);
  77. }
  78. }
  79. function intToUntil (array, length) {
  80. for (var i = 0; i < length; i++) {
  81. array[i] = Math.round((array[i - 1] || 0) + (array[i] * 60000)); // minutes to milliseconds
  82. }
  83. array[length - 1] = Infinity;
  84. }
  85. function mapIndices (source, indices) {
  86. var out = [], i;
  87. for (i = 0; i < indices.length; i++) {
  88. out[i] = source[indices[i]];
  89. }
  90. return out;
  91. }
  92. function unpack (string) {
  93. var data = string.split('|'),
  94. offsets = data[2].split(' '),
  95. indices = data[3].split(''),
  96. untils = data[4].split(' ');
  97. arrayToInt(offsets);
  98. arrayToInt(indices);
  99. arrayToInt(untils);
  100. intToUntil(untils, indices.length);
  101. return {
  102. name : data[0],
  103. abbrs : mapIndices(data[1].split(' '), indices),
  104. offsets : mapIndices(offsets, indices),
  105. untils : untils,
  106. population : data[5] | 0
  107. };
  108. }
  109. /************************************
  110. Zone object
  111. ************************************/
  112. function Zone (packedString) {
  113. if (packedString) {
  114. this._set(unpack(packedString));
  115. }
  116. }
  117. Zone.prototype = {
  118. _set : function (unpacked) {
  119. this.name = unpacked.name;
  120. this.abbrs = unpacked.abbrs;
  121. this.untils = unpacked.untils;
  122. this.offsets = unpacked.offsets;
  123. this.population = unpacked.population;
  124. },
  125. _index : function (timestamp) {
  126. var target = +timestamp,
  127. untils = this.untils,
  128. i;
  129. for (i = 0; i < untils.length; i++) {
  130. if (target < untils[i]) {
  131. return i;
  132. }
  133. }
  134. },
  135. parse : function (timestamp) {
  136. var target = +timestamp,
  137. offsets = this.offsets,
  138. untils = this.untils,
  139. max = untils.length - 1,
  140. offset, offsetNext, offsetPrev, i;
  141. for (i = 0; i < max; i++) {
  142. offset = offsets[i];
  143. offsetNext = offsets[i + 1];
  144. offsetPrev = offsets[i ? i - 1 : i];
  145. if (offset < offsetNext && tz.moveAmbiguousForward) {
  146. offset = offsetNext;
  147. } else if (offset > offsetPrev && tz.moveInvalidForward) {
  148. offset = offsetPrev;
  149. }
  150. if (target < untils[i] - (offset * 60000)) {
  151. return offsets[i];
  152. }
  153. }
  154. return offsets[max];
  155. },
  156. abbr : function (mom) {
  157. return this.abbrs[this._index(mom)];
  158. },
  159. offset : function (mom) {
  160. logError("zone.offset has been deprecated in favor of zone.utcOffset");
  161. return this.offsets[this._index(mom)];
  162. },
  163. utcOffset : function (mom) {
  164. return this.offsets[this._index(mom)];
  165. }
  166. };
  167. /************************************
  168. Current Timezone
  169. ************************************/
  170. function OffsetAt(at) {
  171. var timeString = at.toTimeString();
  172. var abbr = timeString.match(/\([a-z ]+\)/i);
  173. if (abbr && abbr[0]) {
  174. // 17:56:31 GMT-0600 (CST)
  175. // 17:56:31 GMT-0600 (Central Standard Time)
  176. abbr = abbr[0].match(/[A-Z]/g);
  177. abbr = abbr ? abbr.join('') : undefined;
  178. } else {
  179. // 17:56:31 CST
  180. // 17:56:31 GMT+0800 (台北標準時間)
  181. abbr = timeString.match(/[A-Z]{3,5}/g);
  182. abbr = abbr ? abbr[0] : undefined;
  183. }
  184. if (abbr === 'GMT') {
  185. abbr = undefined;
  186. }
  187. this.at = +at;
  188. this.abbr = abbr;
  189. this.offset = at.getTimezoneOffset();
  190. }
  191. function ZoneScore(zone) {
  192. this.zone = zone;
  193. this.offsetScore = 0;
  194. this.abbrScore = 0;
  195. }
  196. ZoneScore.prototype.scoreOffsetAt = function (offsetAt) {
  197. this.offsetScore += Math.abs(this.zone.utcOffset(offsetAt.at) - offsetAt.offset);
  198. if (this.zone.abbr(offsetAt.at).replace(/[^A-Z]/g, '') !== offsetAt.abbr) {
  199. this.abbrScore++;
  200. }
  201. };
  202. function findChange(low, high) {
  203. var mid, diff;
  204. while ((diff = ((high.at - low.at) / 12e4 | 0) * 6e4)) {
  205. mid = new OffsetAt(new Date(low.at + diff));
  206. if (mid.offset === low.offset) {
  207. low = mid;
  208. } else {
  209. high = mid;
  210. }
  211. }
  212. return low;
  213. }
  214. function userOffsets() {
  215. var startYear = new Date().getFullYear() - 2,
  216. last = new OffsetAt(new Date(startYear, 0, 1)),
  217. offsets = [last],
  218. change, next, i;
  219. for (i = 1; i < 48; i++) {
  220. next = new OffsetAt(new Date(startYear, i, 1));
  221. if (next.offset !== last.offset) {
  222. change = findChange(last, next);
  223. offsets.push(change);
  224. offsets.push(new OffsetAt(new Date(change.at + 6e4)));
  225. }
  226. last = next;
  227. }
  228. for (i = 0; i < 4; i++) {
  229. offsets.push(new OffsetAt(new Date(startYear + i, 0, 1)));
  230. offsets.push(new OffsetAt(new Date(startYear + i, 6, 1)));
  231. }
  232. return offsets;
  233. }
  234. function sortZoneScores (a, b) {
  235. if (a.offsetScore !== b.offsetScore) {
  236. return a.offsetScore - b.offsetScore;
  237. }
  238. if (a.abbrScore !== b.abbrScore) {
  239. return a.abbrScore - b.abbrScore;
  240. }
  241. return b.zone.population - a.zone.population;
  242. }
  243. function addToGuesses (name, offsets) {
  244. var i, offset;
  245. arrayToInt(offsets);
  246. for (i = 0; i < offsets.length; i++) {
  247. offset = offsets[i];
  248. guesses[offset] = guesses[offset] || {};
  249. guesses[offset][name] = true;
  250. }
  251. }
  252. function guessesForUserOffsets (offsets) {
  253. var offsetsLength = offsets.length,
  254. filteredGuesses = {},
  255. out = [],
  256. i, j, guessesOffset;
  257. for (i = 0; i < offsetsLength; i++) {
  258. guessesOffset = guesses[offsets[i].offset] || {};
  259. for (j in guessesOffset) {
  260. if (guessesOffset.hasOwnProperty(j)) {
  261. filteredGuesses[j] = true;
  262. }
  263. }
  264. }
  265. for (i in filteredGuesses) {
  266. if (filteredGuesses.hasOwnProperty(i)) {
  267. out.push(names[i]);
  268. }
  269. }
  270. return out;
  271. }
  272. function rebuildGuess () {
  273. // use Intl API when available and returning valid time zone
  274. try {
  275. var intlName = Intl.DateTimeFormat().resolvedOptions().timeZone;
  276. if (intlName && intlName.length > 3) {
  277. var name = names[normalizeName(intlName)];
  278. if (name) {
  279. return name;
  280. }
  281. logError("Moment Timezone found " + intlName + " from the Intl api, but did not have that data loaded.");
  282. }
  283. } catch (e) {
  284. // Intl unavailable, fall back to manual guessing.
  285. }
  286. var offsets = userOffsets(),
  287. offsetsLength = offsets.length,
  288. guesses = guessesForUserOffsets(offsets),
  289. zoneScores = [],
  290. zoneScore, i, j;
  291. for (i = 0; i < guesses.length; i++) {
  292. zoneScore = new ZoneScore(getZone(guesses[i]), offsetsLength);
  293. for (j = 0; j < offsetsLength; j++) {
  294. zoneScore.scoreOffsetAt(offsets[j]);
  295. }
  296. zoneScores.push(zoneScore);
  297. }
  298. zoneScores.sort(sortZoneScores);
  299. return zoneScores.length > 0 ? zoneScores[0].zone.name : undefined;
  300. }
  301. function guess (ignoreCache) {
  302. if (!cachedGuess || ignoreCache) {
  303. cachedGuess = rebuildGuess();
  304. }
  305. return cachedGuess;
  306. }
  307. /************************************
  308. Global Methods
  309. ************************************/
  310. function normalizeName (name) {
  311. return (name || '').toLowerCase().replace(/\//g, '_');
  312. }
  313. function addZone (packed) {
  314. var i, name, split, normalized;
  315. if (typeof packed === "string") {
  316. packed = [packed];
  317. }
  318. for (i = 0; i < packed.length; i++) {
  319. split = packed[i].split('|');
  320. name = split[0];
  321. normalized = normalizeName(name);
  322. zones[normalized] = packed[i];
  323. names[normalized] = name;
  324. addToGuesses(normalized, split[2].split(' '));
  325. }
  326. }
  327. function getZone (name, caller) {
  328. name = normalizeName(name);
  329. var zone = zones[name];
  330. var link;
  331. if (zone instanceof Zone) {
  332. return zone;
  333. }
  334. if (typeof zone === 'string') {
  335. zone = new Zone(zone);
  336. zones[name] = zone;
  337. return zone;
  338. }
  339. // Pass getZone to prevent recursion more than 1 level deep
  340. if (links[name] && caller !== getZone && (link = getZone(links[name], getZone))) {
  341. zone = zones[name] = new Zone();
  342. zone._set(link);
  343. zone.name = names[name];
  344. return zone;
  345. }
  346. return null;
  347. }
  348. function getNames () {
  349. var i, out = [];
  350. for (i in names) {
  351. if (names.hasOwnProperty(i) && (zones[i] || zones[links[i]]) && names[i]) {
  352. out.push(names[i]);
  353. }
  354. }
  355. return out.sort();
  356. }
  357. function addLink (aliases) {
  358. var i, alias, normal0, normal1;
  359. if (typeof aliases === "string") {
  360. aliases = [aliases];
  361. }
  362. for (i = 0; i < aliases.length; i++) {
  363. alias = aliases[i].split('|');
  364. normal0 = normalizeName(alias[0]);
  365. normal1 = normalizeName(alias[1]);
  366. links[normal0] = normal1;
  367. names[normal0] = alias[0];
  368. links[normal1] = normal0;
  369. names[normal1] = alias[1];
  370. }
  371. }
  372. function loadData (data) {
  373. addZone(data.zones);
  374. addLink(data.links);
  375. tz.dataVersion = data.version;
  376. }
  377. function zoneExists (name) {
  378. if (!zoneExists.didShowError) {
  379. zoneExists.didShowError = true;
  380. logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')");
  381. }
  382. return !!getZone(name);
  383. }
  384. function needsOffset (m) {
  385. var isUnixTimestamp = (m._f === 'X' || m._f === 'x');
  386. return !!(m._a && (m._tzm === undefined) && !isUnixTimestamp);
  387. }
  388. function logError (message) {
  389. if (typeof console !== 'undefined' && typeof console.error === 'function') {
  390. console.error(message);
  391. }
  392. }
  393. /************************************
  394. moment.tz namespace
  395. ************************************/
  396. function tz (input) {
  397. var args = Array.prototype.slice.call(arguments, 0, -1),
  398. name = arguments[arguments.length - 1],
  399. zone = getZone(name),
  400. out = moment.utc.apply(null, args);
  401. if (zone && !moment.isMoment(input) && needsOffset(out)) {
  402. out.add(zone.parse(out), 'minutes');
  403. }
  404. out.tz(name);
  405. return out;
  406. }
  407. tz.version = VERSION;
  408. tz.dataVersion = '';
  409. tz._zones = zones;
  410. tz._links = links;
  411. tz._names = names;
  412. tz.add = addZone;
  413. tz.link = addLink;
  414. tz.load = loadData;
  415. tz.zone = getZone;
  416. tz.zoneExists = zoneExists; // deprecated in 0.1.0
  417. tz.guess = guess;
  418. tz.names = getNames;
  419. tz.Zone = Zone;
  420. tz.unpack = unpack;
  421. tz.unpackBase60 = unpackBase60;
  422. tz.needsOffset = needsOffset;
  423. tz.moveInvalidForward = true;
  424. tz.moveAmbiguousForward = false;
  425. /************************************
  426. Interface with Moment.js
  427. ************************************/
  428. var fn = moment.fn;
  429. moment.tz = tz;
  430. moment.defaultZone = null;
  431. moment.updateOffset = function (mom, keepTime) {
  432. var zone = moment.defaultZone,
  433. offset;
  434. if (mom._z === undefined) {
  435. if (zone && needsOffset(mom) && !mom._isUTC) {
  436. mom._d = moment.utc(mom._a)._d;
  437. mom.utc().add(zone.parse(mom), 'minutes');
  438. }
  439. mom._z = zone;
  440. }
  441. if (mom._z) {
  442. offset = mom._z.utcOffset(mom);
  443. if (Math.abs(offset) < 16) {
  444. offset = offset / 60;
  445. }
  446. if (mom.utcOffset !== undefined) {
  447. mom.utcOffset(-offset, keepTime);
  448. } else {
  449. mom.zone(offset, keepTime);
  450. }
  451. }
  452. };
  453. fn.tz = function (name, keepTime) {
  454. if (name) {
  455. this._z = getZone(name);
  456. if (this._z) {
  457. moment.updateOffset(this, keepTime);
  458. } else {
  459. logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/.");
  460. }
  461. return this;
  462. }
  463. if (this._z) { return this._z.name; }
  464. };
  465. function abbrWrap (old) {
  466. return function () {
  467. if (this._z) { return this._z.abbr(this); }
  468. return old.call(this);
  469. };
  470. }
  471. function resetZoneWrap (old) {
  472. return function () {
  473. this._z = null;
  474. return old.apply(this, arguments);
  475. };
  476. }
  477. fn.zoneName = abbrWrap(fn.zoneName);
  478. fn.zoneAbbr = abbrWrap(fn.zoneAbbr);
  479. fn.utc = resetZoneWrap(fn.utc);
  480. moment.tz.setDefault = function(name) {
  481. if (major < 2 || (major === 2 && minor < 9)) {
  482. logError('Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js ' + moment.version + '.');
  483. }
  484. moment.defaultZone = name ? getZone(name) : null;
  485. return moment;
  486. };
  487. // Cloning a moment should include the _z property.
  488. var momentProperties = moment.momentProperties;
  489. if (Object.prototype.toString.call(momentProperties) === '[object Array]') {
  490. // moment 2.8.1+
  491. momentProperties.push('_z');
  492. momentProperties.push('_a');
  493. } else if (momentProperties) {
  494. // moment 2.7.0
  495. momentProperties._z = null;
  496. }
  497. // INJECT DATA
  498. return moment;
  499. }));