moment-timezone-rails 1.0.0

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