moment.js

From disqus.com, 1 Month ago, written in JavaScript, viewed 3 times. This paste is a reply to purify.js from disqus.com - view diff
URL https://pastebin.freepbx.org/view/55e5cb83 Embed
Download Paste or View Raw
  1. //! moment.js
  2. //! version : 2.11.2
  3. //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
  4. //! license : MIT
  5. //! momentjs.com
  6.  
  7. ;(function (global, factory) {
  8.     typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  9.     typeof define === 'function' && define.amd ? define('moment',factory) :
  10.     global.moment = factory()
  11. }(this, function () { 'use strict';
  12.  
  13.     var hookCallback;
  14.  
  15.     function utils_hooks__hooks () {
  16.         return hookCallback.apply(null, arguments);
  17.     }
  18.  
  19.     // This is done to register the method called with moment()
  20.     // without creating circular dependencies.
  21.     function setHookCallback (callback) {
  22.         hookCallback = callback;
  23.     }
  24.  
  25.     function isArray(input) {
  26.         return Object.prototype.toString.call(input) === '[object Array]';
  27.     }
  28.  
  29.     function isDate(input) {
  30.         return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
  31.     }
  32.  
  33.     function map(arr, fn) {
  34.         var res = [], i;
  35.         for (i = 0; i < arr.length; ++i) {
  36.             res.push(fn(arr[i], i));
  37.         }
  38.         return res;
  39.     }
  40.  
  41.     function hasOwnProp(a, b) {
  42.         return Object.prototype.hasOwnProperty.call(a, b);
  43.     }
  44.  
  45.     function extend(a, b) {
  46.         for (var i in b) {
  47.             if (hasOwnProp(b, i)) {
  48.                 a[i] = b[i];
  49.             }
  50.         }
  51.  
  52.         if (hasOwnProp(b, 'toString')) {
  53.             a.toString = b.toString;
  54.         }
  55.  
  56.         if (hasOwnProp(b, 'valueOf')) {
  57.             a.valueOf = b.valueOf;
  58.         }
  59.  
  60.         return a;
  61.     }
  62.  
  63.     function create_utc__createUTC (input, format, locale, strict) {
  64.         return createLocalOrUTC(input, format, locale, strict, true).utc();
  65.     }
  66.  
  67.     function defaultParsingFlags() {
  68.         // We need to deep clone this object.
  69.         return {
  70.             empty           : false,
  71.             unusedTokens    : [],
  72.             unusedInput     : [],
  73.             overflow        : -2,
  74.             charsLeftOver   : 0,
  75.             nullInput       : false,
  76.             invalidMonth    : null,
  77.             invalidFormat   : false,
  78.             userInvalidated : false,
  79.             iso             : false
  80.         };
  81.     }
  82.  
  83.     function getParsingFlags(m) {
  84.         if (m._pf == null) {
  85.             m._pf = defaultParsingFlags();
  86.         }
  87.         return m._pf;
  88.     }
  89.  
  90.     function valid__isValid(m) {
  91.         if (m._isValid == null) {
  92.             var flags = getParsingFlags(m);
  93.             m._isValid = !isNaN(m._d.getTime()) &&
  94.                 flags.overflow < 0 &&
  95.                 !flags.empty &&
  96.                 !flags.invalidMonth &&
  97.                 !flags.invalidWeekday &&
  98.                 !flags.nullInput &&
  99.                 !flags.invalidFormat &&
  100.                 !flags.userInvalidated;
  101.  
  102.             if (m._strict) {
  103.                 m._isValid = m._isValid &&
  104.                     flags.charsLeftOver === 0 &&
  105.                     flags.unusedTokens.length === 0 &&
  106.                     flags.bigHour === undefined;
  107.             }
  108.         }
  109.         return m._isValid;
  110.     }
  111.  
  112.     function valid__createInvalid (flags) {
  113.         var m = create_utc__createUTC(NaN);
  114.         if (flags != null) {
  115.             extend(getParsingFlags(m), flags);
  116.         }
  117.         else {
  118.             getParsingFlags(m).userInvalidated = true;
  119.         }
  120.  
  121.         return m;
  122.     }
  123.  
  124.     function isUndefined(input) {
  125.         return input === void 0;
  126.     }
  127.  
  128.     // Plugins that add properties should also add the key here (null value),
  129.     // so we can properly clone ourselves.
  130.     var momentProperties = utils_hooks__hooks.momentProperties = [];
  131.  
  132.     function copyConfig(to, from) {
  133.         var i, prop, val;
  134.  
  135.         if (!isUndefined(from._isAMomentObject)) {
  136.             to._isAMomentObject = from._isAMomentObject;
  137.         }
  138.         if (!isUndefined(from._i)) {
  139.             to._i = from._i;
  140.         }
  141.         if (!isUndefined(from._f)) {
  142.             to._f = from._f;
  143.         }
  144.         if (!isUndefined(from._l)) {
  145.             to._l = from._l;
  146.         }
  147.         if (!isUndefined(from._strict)) {
  148.             to._strict = from._strict;
  149.         }
  150.         if (!isUndefined(from._tzm)) {
  151.             to._tzm = from._tzm;
  152.         }
  153.         if (!isUndefined(from._isUTC)) {
  154.             to._isUTC = from._isUTC;
  155.         }
  156.         if (!isUndefined(from._offset)) {
  157.             to._offset = from._offset;
  158.         }
  159.         if (!isUndefined(from._pf)) {
  160.             to._pf = getParsingFlags(from);
  161.         }
  162.         if (!isUndefined(from._locale)) {
  163.             to._locale = from._locale;
  164.         }
  165.  
  166.         if (momentProperties.length > 0) {
  167.             for (i in momentProperties) {
  168.                 prop = momentProperties[i];
  169.                 val = from[prop];
  170.                 if (!isUndefined(val)) {
  171.                     to[prop] = val;
  172.                 }
  173.             }
  174.         }
  175.  
  176.         return to;
  177.     }
  178.  
  179.     var updateInProgress = false;
  180.  
  181.     // Moment prototype object
  182.     function Moment(config) {
  183.         copyConfig(this, config);
  184.         this._d = new Date(config._d != null ? config._d.getTime() : NaN);
  185.         // Prevent infinite loop in case updateOffset creates new moment
  186.         // objects.
  187.         if (updateInProgress === false) {
  188.             updateInProgress = true;
  189.             utils_hooks__hooks.updateOffset(this);
  190.             updateInProgress = false;
  191.         }
  192.     }
  193.  
  194.     function isMoment (obj) {
  195.         return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
  196.     }
  197.  
  198.     function absFloor (number) {
  199.         if (number < 0) {
  200.             return Math.ceil(number);
  201.         } else {
  202.             return Math.floor(number);
  203.         }
  204.     }
  205.  
  206.     function toInt(argumentForCoercion) {
  207.         var coercedNumber = +argumentForCoercion,
  208.             value = 0;
  209.  
  210.         if (coercedNumber !== 0 && isFinite(coercedNumber)) {
  211.             value = absFloor(coercedNumber);
  212.         }
  213.  
  214.         return value;
  215.     }
  216.  
  217.     // compare two arrays, return the number of differences
  218.     function compareArrays(array1, array2, dontConvert) {
  219.         var len = Math.min(array1.length, array2.length),
  220.             lengthDiff = Math.abs(array1.length - array2.length),
  221.             diffs = 0,
  222.             i;
  223.         for (i = 0; i < len; i++) {
  224.             if ((dontConvert && array1[i] !== array2[i]) ||
  225.                 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
  226.                 diffs++;
  227.             }
  228.         }
  229.         return diffs + lengthDiff;
  230.     }
  231.  
  232.     function Locale() {
  233.     }
  234.  
  235.     // internal storage for locale config files
  236.     var locales = {};
  237.     var globalLocale;
  238.  
  239.     function normalizeLocale(key) {
  240.         return key ? key.toLowerCase().replace('_', '-') : key;
  241.     }
  242.  
  243.     // pick the locale from the array
  244.     // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
  245.     // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
  246.     function chooseLocale(names) {
  247.         var i = 0, j, next, locale, split;
  248.  
  249.         while (i < names.length) {
  250.             split = normalizeLocale(names[i]).split('-');
  251.             j = split.length;
  252.             next = normalizeLocale(names[i + 1]);
  253.             next = next ? next.split('-') : null;
  254.             while (j > 0) {
  255.                 locale = loadLocale(split.slice(0, j).join('-'));
  256.                 if (locale) {
  257.                     return locale;
  258.                 }
  259.                 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
  260.                     //the next array item is better than a shallower substring of this one
  261.                     break;
  262.                 }
  263.                 j--;
  264.             }
  265.             i++;
  266.         }
  267.         return null;
  268.     }
  269.  
  270.     function loadLocale(name) {
  271.         var oldLocale = null;
  272.         // TODO: Find a better way to register and load all the locales in Node
  273.         if (!locales[name] && (typeof module !== 'undefined') &&
  274.                 module && module.exports) {
  275.             try {
  276.                 oldLocale = globalLocale._abbr;
  277.                 require('./locale/' + name);
  278.                 // because defineLocale currently also sets the global locale, we
  279.                 // want to undo that for lazy loaded locales
  280.                 locale_locales__getSetGlobalLocale(oldLocale);
  281.             } catch (e) { }
  282.         }
  283.         return locales[name];
  284.     }
  285.  
  286.     // This function will load locale and then set the global locale.  If
  287.     // no arguments are passed in, it will simply return the current global
  288.     // locale key.
  289.     function locale_locales__getSetGlobalLocale (key, values) {
  290.         var data;
  291.         if (key) {
  292.             if (isUndefined(values)) {
  293.                 data = locale_locales__getLocale(key);
  294.             }
  295.             else {
  296.                 data = defineLocale(key, values);
  297.             }
  298.  
  299.             if (data) {
  300.                 // moment.duration._locale = moment._locale = data;
  301.                 globalLocale = data;
  302.             }
  303.         }
  304.  
  305.         return globalLocale._abbr;
  306.     }
  307.  
  308.     function defineLocale (name, values) {
  309.         if (values !== null) {
  310.             values.abbr = name;
  311.             locales[name] = locales[name] || new Locale();
  312.             locales[name].set(values);
  313.  
  314.             // backwards compat for now: also set the locale
  315.             locale_locales__getSetGlobalLocale(name);
  316.  
  317.             return locales[name];
  318.         } else {
  319.             // useful for testing
  320.             delete locales[name];
  321.             return null;
  322.         }
  323.     }
  324.  
  325.     // returns locale data
  326.     function locale_locales__getLocale (key) {
  327.         var locale;
  328.  
  329.         if (key && key._locale && key._locale._abbr) {
  330.             key = key._locale._abbr;
  331.         }
  332.  
  333.         if (!key) {
  334.             return globalLocale;
  335.         }
  336.  
  337.         if (!isArray(key)) {
  338.             //short-circuit everything else
  339.             locale = loadLocale(key);
  340.             if (locale) {
  341.                 return locale;
  342.             }
  343.             key = [key];
  344.         }
  345.  
  346.         return chooseLocale(key);
  347.     }
  348.  
  349.     var aliases = {};
  350.  
  351.     function addUnitAlias (unit, shorthand) {
  352.         var lowerCase = unit.toLowerCase();
  353.         aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
  354.     }
  355.  
  356.     function normalizeUnits(units) {
  357.         return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
  358.     }
  359.  
  360.     function normalizeObjectUnits(inputObject) {
  361.         var normalizedInput = {},
  362.             normalizedProp,
  363.             prop;
  364.  
  365.         for (prop in inputObject) {
  366.             if (hasOwnProp(inputObject, prop)) {
  367.                 normalizedProp = normalizeUnits(prop);
  368.                 if (normalizedProp) {
  369.                     normalizedInput[normalizedProp] = inputObject[prop];
  370.                 }
  371.             }
  372.         }
  373.  
  374.         return normalizedInput;
  375.     }
  376.  
  377.     function isFunction(input) {
  378.         return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
  379.     }
  380.  
  381.     function makeGetSet (unit, keepTime) {
  382.         return function (value) {
  383.             if (value != null) {
  384.                 get_set__set(this, unit, value);
  385.                 utils_hooks__hooks.updateOffset(this, keepTime);
  386.                 return this;
  387.             } else {
  388.                 return get_set__get(this, unit);
  389.             }
  390.         };
  391.     }
  392.  
  393.     function get_set__get (mom, unit) {
  394.         return mom.isValid() ?
  395.             mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
  396.     }
  397.  
  398.     function get_set__set (mom, unit, value) {
  399.         if (mom.isValid()) {
  400.             mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
  401.         }
  402.     }
  403.  
  404.     // MOMENTS
  405.  
  406.     function getSet (units, value) {
  407.         var unit;
  408.         if (typeof units === 'object') {
  409.             for (unit in units) {
  410.                 this.set(unit, units[unit]);
  411.             }
  412.         } else {
  413.             units = normalizeUnits(units);
  414.             if (isFunction(this[units])) {
  415.                 return this[units](value);
  416.             }
  417.         }
  418.         return this;
  419.     }
  420.  
  421.     function zeroFill(number, targetLength, forceSign) {
  422.         var absNumber = '' + Math.abs(number),
  423.             zerosToFill = targetLength - absNumber.length,
  424.             sign = number >= 0;
  425.         return (sign ? (forceSign ? '+' : '') : '-') +
  426.             Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
  427.     }
  428.  
  429.     var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
  430.  
  431.     var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
  432.  
  433.     var formatFunctions = {};
  434.  
  435.     var formatTokenFunctions = {};
  436.  
  437.     // token:    'M'
  438.     // padded:   ['MM', 2]
  439.     // ordinal:  'Mo'
  440.     // callback: function () { this.month() + 1 }
  441.     function addFormatToken (token, padded, ordinal, callback) {
  442.         var func = callback;
  443.         if (typeof callback === 'string') {
  444.             func = function () {
  445.                 return this[callback]();
  446.             };
  447.         }
  448.         if (token) {
  449.             formatTokenFunctions[token] = func;
  450.         }
  451.         if (padded) {
  452.             formatTokenFunctions[padded[0]] = function () {
  453.                 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
  454.             };
  455.         }
  456.         if (ordinal) {
  457.             formatTokenFunctions[ordinal] = function () {
  458.                 return this.localeData().ordinal(func.apply(this, arguments), token);
  459.             };
  460.         }
  461.     }
  462.  
  463.     function removeFormattingTokens(input) {
  464.         if (input.match(/\[[\s\S]/)) {
  465.             return input.replace(/^\[|\]$/g, '');
  466.         }
  467.         return input.replace(/\\/g, '');
  468.     }
  469.  
  470.     function makeFormatFunction(format) {
  471.         var array = format.match(formattingTokens), i, length;
  472.  
  473.         for (i = 0, length = array.length; i < length; i++) {
  474.             if (formatTokenFunctions[array[i]]) {
  475.                 array[i] = formatTokenFunctions[array[i]];
  476.             } else {
  477.                 array[i] = removeFormattingTokens(array[i]);
  478.             }
  479.         }
  480.  
  481.         return function (mom) {
  482.             var output = '';
  483.             for (i = 0; i < length; i++) {
  484.                 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
  485.             }
  486.             return output;
  487.         };
  488.     }
  489.  
  490.     // format date using native date object
  491.     function formatMoment(m, format) {
  492.         if (!m.isValid()) {
  493.             return m.localeData().invalidDate();
  494.         }
  495.  
  496.         format = expandFormat(format, m.localeData());
  497.         formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
  498.  
  499.         return formatFunctions[format](m);
  500.     }
  501.  
  502.     function expandFormat(format, locale) {
  503.         var i = 5;
  504.  
  505.         function replaceLongDateFormatTokens(input) {
  506.             return locale.longDateFormat(input) || input;
  507.         }
  508.  
  509.         localFormattingTokens.lastIndex = 0;
  510.         while (i >= 0 && localFormattingTokens.test(format)) {
  511.             format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
  512.             localFormattingTokens.lastIndex = 0;
  513.             i -= 1;
  514.         }
  515.  
  516.         return format;
  517.     }
  518.  
  519.     var match1         = /\d/;            //       0 - 9
  520.     var match2         = /\d\d/;          //      00 - 99
  521.     var match3         = /\d{3}/;         //     000 - 999
  522.     var match4         = /\d{4}/;         //    0000 - 9999
  523.     var match6         = /[+-]?\d{6}/;    // -999999 - 999999
  524.     var match1to2      = /\d\d?/;         //       0 - 99
  525.     var match3to4      = /\d\d\d\d?/;     //     999 - 9999
  526.     var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
  527.     var match1to3      = /\d{1,3}/;       //       0 - 999
  528.     var match1to4      = /\d{1,4}/;       //       0 - 9999
  529.     var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
  530.  
  531.     var matchUnsigned  = /\d+/;           //       0 - inf
  532.     var matchSigned    = /[+-]?\d+/;      //    -inf - inf
  533.  
  534.     var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
  535.     var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
  536.  
  537.     var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
  538.  
  539.     // any word (or two) characters or numbers including two/three word month in arabic.
  540.     // includes scottish gaelic two word and hyphenated months
  541.     var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
  542.  
  543.  
  544.     var regexes = {};
  545.  
  546.     function addRegexToken (token, regex, strictRegex) {
  547.         regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
  548.             return (isStrict && strictRegex) ? strictRegex : regex;
  549.         };
  550.     }
  551.  
  552.     function getParseRegexForToken (token, config) {
  553.         if (!hasOwnProp(regexes, token)) {
  554.             return new RegExp(unescapeFormat(token));
  555.         }
  556.  
  557.         return regexes[token](config._strict, config._locale);
  558.     }
  559.  
  560.     // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
  561.     function unescapeFormat(s) {
  562.         return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
  563.             return p1 || p2 || p3 || p4;
  564.         }));
  565.     }
  566.  
  567.     function regexEscape(s) {
  568.         return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  569.     }
  570.  
  571.     var tokens = {};
  572.  
  573.     function addParseToken (token, callback) {
  574.         var i, func = callback;
  575.         if (typeof token === 'string') {
  576.             token = [token];
  577.         }
  578.         if (typeof callback === 'number') {
  579.             func = function (input, array) {
  580.                 array[callback] = toInt(input);
  581.             };
  582.         }
  583.         for (i = 0; i < token.length; i++) {
  584.             tokens[token[i]] = func;
  585.         }
  586.     }
  587.  
  588.     function addWeekParseToken (token, callback) {
  589.         addParseToken(token, function (input, array, config, token) {
  590.             config._w = config._w || {};
  591.             callback(input, config._w, config, token);
  592.         });
  593.     }
  594.  
  595.     function addTimeToArrayFromToken(token, input, config) {
  596.         if (input != null && hasOwnProp(tokens, token)) {
  597.             tokens[token](input, config._a, config, token);
  598.         }
  599.     }
  600.  
  601.     var YEAR = 0;
  602.     var MONTH = 1;
  603.     var DATE = 2;
  604.     var HOUR = 3;
  605.     var MINUTE = 4;
  606.     var SECOND = 5;
  607.     var MILLISECOND = 6;
  608.     var WEEK = 7;
  609.     var WEEKDAY = 8;
  610.  
  611.     function daysInMonth(year, month) {
  612.         return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
  613.     }
  614.  
  615.     // FORMATTING
  616.  
  617.     addFormatToken('M', ['MM', 2], 'Mo', function () {
  618.         return this.month() + 1;
  619.     });
  620.  
  621.     addFormatToken('MMM', 0, 0, function (format) {
  622.         return this.localeData().monthsShort(this, format);
  623.     });
  624.  
  625.     addFormatToken('MMMM', 0, 0, function (format) {
  626.         return this.localeData().months(this, format);
  627.     });
  628.  
  629.     // ALIASES
  630.  
  631.     addUnitAlias('month', 'M');
  632.  
  633.     // PARSING
  634.  
  635.     addRegexToken('M',    match1to2);
  636.     addRegexToken('MM',   match1to2, match2);
  637.     addRegexToken('MMM',  function (isStrict, locale) {
  638.         return locale.monthsShortRegex(isStrict);
  639.     });
  640.     addRegexToken('MMMM', function (isStrict, locale) {
  641.         return locale.monthsRegex(isStrict);
  642.     });
  643.  
  644.     addParseToken(['M', 'MM'], function (input, array) {
  645.         array[MONTH] = toInt(input) - 1;
  646.     });
  647.  
  648.     addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
  649.         var month = config._locale.monthsParse(input, token, config._strict);
  650.         // if we didn't find a month name, mark the date as invalid.
  651.         if (month != null) {
  652.             array[MONTH] = month;
  653.         } else {
  654.             getParsingFlags(config).invalidMonth = input;
  655.         }
  656.     });
  657.  
  658.     // LOCALES
  659.  
  660.     var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
  661.     var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
  662.     function localeMonths (m, format) {
  663.         return isArray(this._months) ? this._months[m.month()] :
  664.             this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
  665.     }
  666.  
  667.     var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
  668.     function localeMonthsShort (m, format) {
  669.         return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
  670.             this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
  671.     }
  672.  
  673.     function localeMonthsParse (monthName, format, strict) {
  674.         var i, mom, regex;
  675.  
  676.         if (!this._monthsParse) {
  677.             this._monthsParse = [];
  678.             this._longMonthsParse = [];
  679.             this._shortMonthsParse = [];
  680.         }
  681.  
  682.         for (i = 0; i < 12; i++) {
  683.             // make the regex if we don't have it already
  684.             mom = create_utc__createUTC([2000, i]);
  685.             if (strict && !this._longMonthsParse[i]) {
  686.                 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
  687.                 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
  688.             }
  689.             if (!strict && !this._monthsParse[i]) {
  690.                 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
  691.                 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
  692.             }
  693.             // test the regex
  694.             if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
  695.                 return i;
  696.             } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
  697.                 return i;
  698.             } else if (!strict && this._monthsParse[i].test(monthName)) {
  699.                 return i;
  700.             }
  701.         }
  702.     }
  703.  
  704.     // MOMENTS
  705.  
  706.     function setMonth (mom, value) {
  707.         var dayOfMonth;
  708.  
  709.         if (!mom.isValid()) {
  710.             // No op
  711.             return mom;
  712.         }
  713.  
  714.         // TODO: Move this out of here!
  715.         if (typeof value === 'string') {
  716.             value = mom.localeData().monthsParse(value);
  717.             // TODO: Another silent failure?
  718.             if (typeof value !== 'number') {
  719.                 return mom;
  720.             }
  721.         }
  722.  
  723.         dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
  724.         mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
  725.         return mom;
  726.     }
  727.  
  728.     function getSetMonth (value) {
  729.         if (value != null) {
  730.             setMonth(this, value);
  731.             utils_hooks__hooks.updateOffset(this, true);
  732.             return this;
  733.         } else {
  734.             return get_set__get(this, 'Month');
  735.         }
  736.     }
  737.  
  738.     function getDaysInMonth () {
  739.         return daysInMonth(this.year(), this.month());
  740.     }
  741.  
  742.     var defaultMonthsShortRegex = matchWord;
  743.     function monthsShortRegex (isStrict) {
  744.         if (this._monthsParseExact) {
  745.             if (!hasOwnProp(this, '_monthsRegex')) {
  746.                 computeMonthsParse.call(this);
  747.             }
  748.             if (isStrict) {
  749.                 return this._monthsShortStrictRegex;
  750.             } else {
  751.                 return this._monthsShortRegex;
  752.             }
  753.         } else {
  754.             return this._monthsShortStrictRegex && isStrict ?
  755.                 this._monthsShortStrictRegex : this._monthsShortRegex;
  756.         }
  757.     }
  758.  
  759.     var defaultMonthsRegex = matchWord;
  760.     function monthsRegex (isStrict) {
  761.         if (this._monthsParseExact) {
  762.             if (!hasOwnProp(this, '_monthsRegex')) {
  763.                 computeMonthsParse.call(this);
  764.             }
  765.             if (isStrict) {
  766.                 return this._monthsStrictRegex;
  767.             } else {
  768.                 return this._monthsRegex;
  769.             }
  770.         } else {
  771.             return this._monthsStrictRegex && isStrict ?
  772.                 this._monthsStrictRegex : this._monthsRegex;
  773.         }
  774.     }
  775.  
  776.     function computeMonthsParse () {
  777.         function cmpLenRev(a, b) {
  778.             return b.length - a.length;
  779.         }
  780.  
  781.         var shortPieces = [], longPieces = [], mixedPieces = [],
  782.             i, mom;
  783.         for (i = 0; i < 12; i++) {
  784.             // make the regex if we don't have it already
  785.             mom = create_utc__createUTC([2000, i]);
  786.             shortPieces.push(this.monthsShort(mom, ''));
  787.             longPieces.push(this.months(mom, ''));
  788.             mixedPieces.push(this.months(mom, ''));
  789.             mixedPieces.push(this.monthsShort(mom, ''));
  790.         }
  791.         // Sorting makes sure if one month (or abbr) is a prefix of another it
  792.         // will match the longer piece.
  793.         shortPieces.sort(cmpLenRev);
  794.         longPieces.sort(cmpLenRev);
  795.         mixedPieces.sort(cmpLenRev);
  796.         for (i = 0; i < 12; i++) {
  797.             shortPieces[i] = regexEscape(shortPieces[i]);
  798.             longPieces[i] = regexEscape(longPieces[i]);
  799.             mixedPieces[i] = regexEscape(mixedPieces[i]);
  800.         }
  801.  
  802.         this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
  803.         this._monthsShortRegex = this._monthsRegex;
  804.         this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i');
  805.         this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i');
  806.     }
  807.  
  808.     function checkOverflow (m) {
  809.         var overflow;
  810.         var a = m._a;
  811.  
  812.         if (a && getParsingFlags(m).overflow === -2) {
  813.             overflow =
  814.                 a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
  815.                 a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
  816.                 a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
  817.                 a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
  818.                 a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
  819.                 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
  820.                 -1;
  821.  
  822.             if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
  823.                 overflow = DATE;
  824.             }
  825.             if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
  826.                 overflow = WEEK;
  827.             }
  828.             if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
  829.                 overflow = WEEKDAY;
  830.             }
  831.  
  832.             getParsingFlags(m).overflow = overflow;
  833.         }
  834.  
  835.         return m;
  836.     }
  837.  
  838.     function warn(msg) {
  839.         if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
  840.                 (typeof console !==  'undefined') && console.warn) {
  841.             console.warn('Deprecation warning: ' + msg);
  842.         }
  843.     }
  844.  
  845.     function deprecate(msg, fn) {
  846.         var firstTime = true;
  847.  
  848.         return extend(function () {
  849.             if (firstTime) {
  850.                 warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
  851.                 firstTime = false;
  852.             }
  853.             return fn.apply(this, arguments);
  854.         }, fn);
  855.     }
  856.  
  857.     var deprecations = {};
  858.  
  859.     function deprecateSimple(name, msg) {
  860.         if (!deprecations[name]) {
  861.             warn(msg);
  862.             deprecations[name] = true;
  863.         }
  864.     }
  865.  
  866.     utils_hooks__hooks.suppressDeprecationWarnings = false;
  867.  
  868.     // iso 8601 regex
  869.     // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
  870.     var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
  871.     var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
  872.  
  873.     var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
  874.  
  875.     var isoDates = [
  876.         ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
  877.         ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
  878.         ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
  879.         ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
  880.         ['YYYY-DDD', /\d{4}-\d{3}/],
  881.         ['YYYY-MM', /\d{4}-\d\d/, false],
  882.         ['YYYYYYMMDD', /[+-]\d{10}/],
  883.         ['YYYYMMDD', /\d{8}/],
  884.         // YYYYMM is NOT allowed by the standard
  885.         ['GGGG[W]WWE', /\d{4}W\d{3}/],
  886.         ['GGGG[W]WW', /\d{4}W\d{2}/, false],
  887.         ['YYYYDDD', /\d{7}/]
  888.     ];
  889.  
  890.     // iso time formats and regexes
  891.     var isoTimes = [
  892.         ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
  893.         ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
  894.         ['HH:mm:ss', /\d\d:\d\d:\d\d/],
  895.         ['HH:mm', /\d\d:\d\d/],
  896.         ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
  897.         ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
  898.         ['HHmmss', /\d\d\d\d\d\d/],
  899.         ['HHmm', /\d\d\d\d/],
  900.         ['HH', /\d\d/]
  901.     ];
  902.  
  903.     var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
  904.  
  905.     // date from iso format
  906.     function configFromISO(config) {
  907.         var i, l,
  908.             string = config._i,
  909.             match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
  910.             allowTime, dateFormat, timeFormat, tzFormat;
  911.  
  912.         if (match) {
  913.             getParsingFlags(config).iso = true;
  914.  
  915.             for (i = 0, l = isoDates.length; i < l; i++) {
  916.                 if (isoDates[i][1].exec(match[1])) {
  917.                     dateFormat = isoDates[i][0];
  918.                     allowTime = isoDates[i][2] !== false;
  919.                     break;
  920.                 }
  921.             }
  922.             if (dateFormat == null) {
  923.                 config._isValid = false;
  924.                 return;
  925.             }
  926.             if (match[3]) {
  927.                 for (i = 0, l = isoTimes.length; i < l; i++) {
  928.                     if (isoTimes[i][1].exec(match[3])) {
  929.                         // match[2] should be 'T' or space
  930.                         timeFormat = (match[2] || ' ') + isoTimes[i][0];
  931.                         break;
  932.                     }
  933.                 }
  934.                 if (timeFormat == null) {
  935.                     config._isValid = false;
  936.                     return;
  937.                 }
  938.             }
  939.             if (!allowTime && timeFormat != null) {
  940.                 config._isValid = false;
  941.                 return;
  942.             }
  943.             if (match[4]) {
  944.                 if (tzRegex.exec(match[4])) {
  945.                     tzFormat = 'Z';
  946.                 } else {
  947.                     config._isValid = false;
  948.                     return;
  949.                 }
  950.             }
  951.             config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
  952.             configFromStringAndFormat(config);
  953.         } else {
  954.             config._isValid = false;
  955.         }
  956.     }
  957.  
  958.     // date from iso format or fallback
  959.     function configFromString(config) {
  960.         var matched = aspNetJsonRegex.exec(config._i);
  961.  
  962.         if (matched !== null) {
  963.             config._d = new Date(+matched[1]);
  964.             return;
  965.         }
  966.  
  967.         configFromISO(config);
  968.         if (config._isValid === false) {
  969.             delete config._isValid;
  970.             utils_hooks__hooks.createFromInputFallback(config);
  971.         }
  972.     }
  973.  
  974.     utils_hooks__hooks.createFromInputFallback = deprecate(
  975.         'moment construction falls back to js Date. This is ' +
  976.         'discouraged and will be removed in upcoming major ' +
  977.         'release. Please refer to ' +
  978.         'https://github.com/moment/moment/issues/1407 for more info.',
  979.         function (config) {
  980.             config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
  981.         }
  982.     );
  983.  
  984.     function createDate (y, m, d, h, M, s, ms) {
  985.         //can't just apply() to create a date:
  986.         //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
  987.         var date = new Date(y, m, d, h, M, s, ms);
  988.  
  989.         //the date constructor remaps years 0-99 to 1900-1999
  990.         if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
  991.             date.setFullYear(y);
  992.         }
  993.         return date;
  994.     }
  995.  
  996.     function createUTCDate (y) {
  997.         var date = new Date(Date.UTC.apply(null, arguments));
  998.  
  999.         //the Date.UTC function remaps years 0-99 to 1900-1999
  1000.         if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
  1001.             date.setUTCFullYear(y);
  1002.         }
  1003.         return date;
  1004.     }
  1005.  
  1006.     // FORMATTING
  1007.  
  1008.     addFormatToken('Y', 0, 0, function () {
  1009.         var y = this.year();
  1010.         return y <= 9999 ? '' + y : '+' + y;
  1011.     });
  1012.  
  1013.     addFormatToken(0, ['YY', 2], 0, function () {
  1014.         return this.year() % 100;
  1015.     });
  1016.  
  1017.     addFormatToken(0, ['YYYY',   4],       0, 'year');
  1018.     addFormatToken(0, ['YYYYY',  5],       0, 'year');
  1019.     addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
  1020.  
  1021.     // ALIASES
  1022.  
  1023.     addUnitAlias('year', 'y');
  1024.  
  1025.     // PARSING
  1026.  
  1027.     addRegexToken('Y',      matchSigned);
  1028.     addRegexToken('YY',     match1to2, match2);
  1029.     addRegexToken('YYYY',   match1to4, match4);
  1030.     addRegexToken('YYYYY',  match1to6, match6);
  1031.     addRegexToken('YYYYYY', match1to6, match6);
  1032.  
  1033.     addParseToken(['YYYYY', 'YYYYYY'], YEAR);
  1034.     addParseToken('YYYY', function (input, array) {
  1035.         array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
  1036.     });
  1037.     addParseToken('YY', function (input, array) {
  1038.         array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
  1039.     });
  1040.     addParseToken('Y', function (input, array) {
  1041.         array[YEAR] = parseInt(input, 10);
  1042.     });
  1043.  
  1044.     // HELPERS
  1045.  
  1046.     function daysInYear(year) {
  1047.         return isLeapYear(year) ? 366 : 365;
  1048.     }
  1049.  
  1050.     function isLeapYear(year) {
  1051.         return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
  1052.     }
  1053.  
  1054.     // HOOKS
  1055.  
  1056.     utils_hooks__hooks.parseTwoDigitYear = function (input) {
  1057.         return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
  1058.     };
  1059.  
  1060.     // MOMENTS
  1061.  
  1062.     var getSetYear = makeGetSet('FullYear', false);
  1063.  
  1064.     function getIsLeapYear () {
  1065.         return isLeapYear(this.year());
  1066.     }
  1067.  
  1068.     // start-of-first-week - start-of-year
  1069.     function firstWeekOffset(year, dow, doy) {
  1070.         var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
  1071.             fwd = 7 + dow - doy,
  1072.             // first-week day local weekday -- which local weekday is fwd
  1073.             fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
  1074.  
  1075.         return -fwdlw + fwd - 1;
  1076.     }
  1077.  
  1078.     //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
  1079.     function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
  1080.         var localWeekday = (7 + weekday - dow) % 7,
  1081.             weekOffset = firstWeekOffset(year, dow, doy),
  1082.             dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
  1083.             resYear, resDayOfYear;
  1084.  
  1085.         if (dayOfYear <= 0) {
  1086.             resYear = year - 1;
  1087.             resDayOfYear = daysInYear(resYear) + dayOfYear;
  1088.         } else if (dayOfYear > daysInYear(year)) {
  1089.             resYear = year + 1;
  1090.             resDayOfYear = dayOfYear - daysInYear(year);
  1091.         } else {
  1092.             resYear = year;
  1093.             resDayOfYear = dayOfYear;
  1094.         }
  1095.  
  1096.         return {
  1097.             year: resYear,
  1098.             dayOfYear: resDayOfYear
  1099.         };
  1100.     }
  1101.  
  1102.     function weekOfYear(mom, dow, doy) {
  1103.         var weekOffset = firstWeekOffset(mom.year(), dow, doy),
  1104.             week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
  1105.             resWeek, resYear;
  1106.  
  1107.         if (week < 1) {
  1108.             resYear = mom.year() - 1;
  1109.             resWeek = week + weeksInYear(resYear, dow, doy);
  1110.         } else if (week > weeksInYear(mom.year(), dow, doy)) {
  1111.             resWeek = week - weeksInYear(mom.year(), dow, doy);
  1112.             resYear = mom.year() + 1;
  1113.         } else {
  1114.             resYear = mom.year();
  1115.             resWeek = week;
  1116.         }
  1117.  
  1118.         return {
  1119.             week: resWeek,
  1120.             year: resYear
  1121.         };
  1122.     }
  1123.  
  1124.     function weeksInYear(year, dow, doy) {
  1125.         var weekOffset = firstWeekOffset(year, dow, doy),
  1126.             weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
  1127.         return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
  1128.     }
  1129.  
  1130.     // Pick the first defined of two or three arguments.
  1131.     function defaults(a, b, c) {
  1132.         if (a != null) {
  1133.             return a;
  1134.         }
  1135.         if (b != null) {
  1136.             return b;
  1137.         }
  1138.         return c;
  1139.     }
  1140.  
  1141.     function currentDateArray(config) {
  1142.         // hooks is actually the exported moment object
  1143.         var nowValue = new Date(utils_hooks__hooks.now());
  1144.         if (config._useUTC) {
  1145.             return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
  1146.         }
  1147.         return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
  1148.     }
  1149.  
  1150.     // convert an array to a date.
  1151.     // the array should mirror the parameters below
  1152.     // note: all values past the year are optional and will default to the lowest possible value.
  1153.     // [year, month, day , hour, minute, second, millisecond]
  1154.     function configFromArray (config) {
  1155.         var i, date, input = [], currentDate, yearToUse;
  1156.  
  1157.         if (config._d) {
  1158.             return;
  1159.         }
  1160.  
  1161.         currentDate = currentDateArray(config);
  1162.  
  1163.         //compute day of the year from weeks and weekdays
  1164.         if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
  1165.             dayOfYearFromWeekInfo(config);
  1166.         }
  1167.  
  1168.         //if the day of the year is set, figure out what it is
  1169.         if (config._dayOfYear) {
  1170.             yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
  1171.  
  1172.             if (config._dayOfYear > daysInYear(yearToUse)) {
  1173.                 getParsingFlags(config)._overflowDayOfYear = true;
  1174.             }
  1175.  
  1176.             date = createUTCDate(yearToUse, 0, config._dayOfYear);
  1177.             config._a[MONTH] = date.getUTCMonth();
  1178.             config._a[DATE] = date.getUTCDate();
  1179.         }
  1180.  
  1181.         // Default to current date.
  1182.         // * if no year, month, day of month are given, default to today
  1183.         // * if day of month is given, default month and year
  1184.         // * if month is given, default only year
  1185.         // * if year is given, don't default anything
  1186.         for (i = 0; i < 3 && config._a[i] == null; ++i) {
  1187.             config._a[i] = input[i] = currentDate[i];
  1188.         }
  1189.  
  1190.         // Zero out whatever was not defaulted, including time
  1191.         for (; i < 7; i++) {
  1192.             config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
  1193.         }
  1194.  
  1195.         // Check for 24:00:00.000
  1196.         if (config._a[HOUR] === 24 &&
  1197.                 config._a[MINUTE] === 0 &&
  1198.                 config._a[SECOND] === 0 &&
  1199.                 config._a[MILLISECOND] === 0) {
  1200.             config._nextDay = true;
  1201.             config._a[HOUR] = 0;
  1202.         }
  1203.  
  1204.         config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
  1205.         // Apply timezone offset from input. The actual utcOffset can be changed
  1206.         // with parseZone.
  1207.         if (config._tzm != null) {
  1208.             config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
  1209.         }
  1210.  
  1211.         if (config._nextDay) {
  1212.             config._a[HOUR] = 24;
  1213.         }
  1214.     }
  1215.  
  1216.     function dayOfYearFromWeekInfo(config) {
  1217.         var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
  1218.  
  1219.         w = config._w;
  1220.         if (w.GG != null || w.W != null || w.E != null) {
  1221.             dow = 1;
  1222.             doy = 4;
  1223.  
  1224.             // TODO: We need to take the current isoWeekYear, but that depends on
  1225.             // how we interpret now (local, utc, fixed offset). So create
  1226.             // a now version of current config (take local/utc/offset flags, and
  1227.             // create now).
  1228.             weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
  1229.             week = defaults(w.W, 1);
  1230.             weekday = defaults(w.E, 1);
  1231.             if (weekday < 1 || weekday > 7) {
  1232.                 weekdayOverflow = true;
  1233.             }
  1234.         } else {
  1235.             dow = config._locale._week.dow;
  1236.             doy = config._locale._week.doy;
  1237.  
  1238.             weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
  1239.             week = defaults(w.w, 1);
  1240.  
  1241.             if (w.d != null) {
  1242.                 // weekday -- low day numbers are considered next week
  1243.                 weekday = w.d;
  1244.                 if (weekday < 0 || weekday > 6) {
  1245.                     weekdayOverflow = true;
  1246.                 }
  1247.             } else if (w.e != null) {
  1248.                 // local weekday -- counting starts from begining of week
  1249.                 weekday = w.e + dow;
  1250.                 if (w.e < 0 || w.e > 6) {
  1251.                     weekdayOverflow = true;
  1252.                 }
  1253.             } else {
  1254.                 // default to begining of week
  1255.                 weekday = dow;
  1256.             }
  1257.         }
  1258.         if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
  1259.             getParsingFlags(config)._overflowWeeks = true;
  1260.         } else if (weekdayOverflow != null) {
  1261.             getParsingFlags(config)._overflowWeekday = true;
  1262.         } else {
  1263.             temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
  1264.             config._a[YEAR] = temp.year;
  1265.             config._dayOfYear = temp.dayOfYear;
  1266.         }
  1267.     }
  1268.  
  1269.     // constant that refers to the ISO standard
  1270.     utils_hooks__hooks.ISO_8601 = function () {};
  1271.  
  1272.     // date from string and format string
  1273.     function configFromStringAndFormat(config) {
  1274.         // TODO: Move this to another part of the creation flow to prevent circular deps
  1275.         if (config._f === utils_hooks__hooks.ISO_8601) {
  1276.             configFromISO(config);
  1277.             return;
  1278.         }
  1279.  
  1280.         config._a = [];
  1281.         getParsingFlags(config).empty = true;
  1282.  
  1283.         // This array is used to make a Date, either with `new Date` or `Date.UTC`
  1284.         var string = '' + config._i,
  1285.             i, parsedInput, tokens, token, skipped,
  1286.             stringLength = string.length,
  1287.             totalParsedInputLength = 0;
  1288.  
  1289.         tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
  1290.  
  1291.         for (i = 0; i < tokens.length; i++) {
  1292.             token = tokens[i];
  1293.             parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
  1294.             // console.log('token', token, 'parsedInput', parsedInput,
  1295.             //         'regex', getParseRegexForToken(token, config));
  1296.             if (parsedInput) {
  1297.                 skipped = string.substr(0, string.indexOf(parsedInput));
  1298.                 if (skipped.length > 0) {
  1299.                     getParsingFlags(config).unusedInput.push(skipped);
  1300.                 }
  1301.                 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
  1302.                 totalParsedInputLength += parsedInput.length;
  1303.             }
  1304.             // don't parse if it's not a known token
  1305.             if (formatTokenFunctions[token]) {
  1306.                 if (parsedInput) {
  1307.                     getParsingFlags(config).empty = false;
  1308.                 }
  1309.                 else {
  1310.                     getParsingFlags(config).unusedTokens.push(token);
  1311.                 }
  1312.                 addTimeToArrayFromToken(token, parsedInput, config);
  1313.             }
  1314.             else if (config._strict && !parsedInput) {
  1315.                 getParsingFlags(config).unusedTokens.push(token);
  1316.             }
  1317.         }
  1318.  
  1319.         // add remaining unparsed input length to the string
  1320.         getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
  1321.         if (string.length > 0) {
  1322.             getParsingFlags(config).unusedInput.push(string);
  1323.         }
  1324.  
  1325.         // clear _12h flag if hour is <= 12
  1326.         if (getParsingFlags(config).bigHour === true &&
  1327.                 config._a[HOUR] <= 12 &&
  1328.                 config._a[HOUR] > 0) {
  1329.             getParsingFlags(config).bigHour = undefined;
  1330.         }
  1331.         // handle meridiem
  1332.         config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
  1333.  
  1334.         configFromArray(config);
  1335.         checkOverflow(config);
  1336.     }
  1337.  
  1338.  
  1339.     function meridiemFixWrap (locale, hour, meridiem) {
  1340.         var isPm;
  1341.  
  1342.         if (meridiem == null) {
  1343.             // nothing to do
  1344.             return hour;
  1345.         }
  1346.         if (locale.meridiemHour != null) {
  1347.             return locale.meridiemHour(hour, meridiem);
  1348.         } else if (locale.isPM != null) {
  1349.             // Fallback
  1350.             isPm = locale.isPM(meridiem);
  1351.             if (isPm && hour < 12) {
  1352.                 hour += 12;
  1353.             }
  1354.             if (!isPm && hour === 12) {
  1355.                 hour = 0;
  1356.             }
  1357.             return hour;
  1358.         } else {
  1359.             // this is not supposed to happen
  1360.             return hour;
  1361.         }
  1362.     }
  1363.  
  1364.     // date from string and array of format strings
  1365.     function configFromStringAndArray(config) {
  1366.         var tempConfig,
  1367.             bestMoment,
  1368.  
  1369.             scoreToBeat,
  1370.             i,
  1371.             currentScore;
  1372.  
  1373.         if (config._f.length === 0) {
  1374.             getParsingFlags(config).invalidFormat = true;
  1375.             config._d = new Date(NaN);
  1376.             return;
  1377.         }
  1378.  
  1379.         for (i = 0; i < config._f.length; i++) {
  1380.             currentScore = 0;
  1381.             tempConfig = copyConfig({}, config);
  1382.             if (config._useUTC != null) {
  1383.                 tempConfig._useUTC = config._useUTC;
  1384.             }
  1385.             tempConfig._f = config._f[i];
  1386.             configFromStringAndFormat(tempConfig);
  1387.  
  1388.             if (!valid__isValid(tempConfig)) {
  1389.                 continue;
  1390.             }
  1391.  
  1392.             // if there is any input that was not parsed add a penalty for that format
  1393.             currentScore += getParsingFlags(tempConfig).charsLeftOver;
  1394.  
  1395.             //or tokens
  1396.             currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
  1397.  
  1398.             getParsingFlags(tempConfig).score = currentScore;
  1399.  
  1400.             if (scoreToBeat == null || currentScore < scoreToBeat) {
  1401.                 scoreToBeat = currentScore;
  1402.                 bestMoment = tempConfig;
  1403.             }
  1404.         }
  1405.  
  1406.         extend(config, bestMoment || tempConfig);
  1407.     }
  1408.  
  1409.     function configFromObject(config) {
  1410.         if (config._d) {
  1411.             return;
  1412.         }
  1413.  
  1414.         var i = normalizeObjectUnits(config._i);
  1415.         config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
  1416.             return obj && parseInt(obj, 10);
  1417.         });
  1418.  
  1419.         configFromArray(config);
  1420.     }
  1421.  
  1422.     function createFromConfig (config) {
  1423.         var res = new Moment(checkOverflow(prepareConfig(config)));
  1424.         if (res._nextDay) {
  1425.             // Adding is smart enough around DST
  1426.             res.add(1, 'd');
  1427.             res._nextDay = undefined;
  1428.         }
  1429.  
  1430.         return res;
  1431.     }
  1432.  
  1433.     function prepareConfig (config) {
  1434.         var input = config._i,
  1435.             format = config._f;
  1436.  
  1437.         config._locale = config._locale || locale_locales__getLocale(config._l);
  1438.  
  1439.         if (input === null || (format === undefined && input === '')) {
  1440.             return valid__createInvalid({nullInput: true});
  1441.         }
  1442.  
  1443.         if (typeof input === 'string') {
  1444.             config._i = input = config._locale.preparse(input);
  1445.         }
  1446.  
  1447.         if (isMoment(input)) {
  1448.             return new Moment(checkOverflow(input));
  1449.         } else if (isArray(format)) {
  1450.             configFromStringAndArray(config);
  1451.         } else if (format) {
  1452.             configFromStringAndFormat(config);
  1453.         } else if (isDate(input)) {
  1454.             config._d = input;
  1455.         } else {
  1456.             configFromInput(config);
  1457.         }
  1458.  
  1459.         if (!valid__isValid(config)) {
  1460.             config._d = null;
  1461.         }
  1462.  
  1463.         return config;
  1464.     }
  1465.  
  1466.     function configFromInput(config) {
  1467.         var input = config._i;
  1468.         if (input === undefined) {
  1469.             config._d = new Date(utils_hooks__hooks.now());
  1470.         } else if (isDate(input)) {
  1471.             config._d = new Date(+input);
  1472.         } else if (typeof input === 'string') {
  1473.             configFromString(config);
  1474.         } else if (isArray(input)) {
  1475.             config._a = map(input.slice(0), function (obj) {
  1476.                 return parseInt(obj, 10);
  1477.             });
  1478.             configFromArray(config);
  1479.         } else if (typeof(input) === 'object') {
  1480.             configFromObject(config);
  1481.         } else if (typeof(input) === 'number') {
  1482.             // from milliseconds
  1483.             config._d = new Date(input);
  1484.         } else {
  1485.             utils_hooks__hooks.createFromInputFallback(config);
  1486.         }
  1487.     }
  1488.  
  1489.     function createLocalOrUTC (input, format, locale, strict, isUTC) {
  1490.         var c = {};
  1491.  
  1492.         if (typeof(locale) === 'boolean') {
  1493.             strict = locale;
  1494.             locale = undefined;
  1495.         }
  1496.         // object construction must be done this way.
  1497.         // https://github.com/moment/moment/issues/1423
  1498.         c._isAMomentObject = true;
  1499.         c._useUTC = c._isUTC = isUTC;
  1500.         c._l = locale;
  1501.         c._i = input;
  1502.         c._f = format;
  1503.         c._strict = strict;
  1504.  
  1505.         return createFromConfig(c);
  1506.     }
  1507.  
  1508.     function local__createLocal (input, format, locale, strict) {
  1509.         return createLocalOrUTC(input, format, locale, strict, false);
  1510.     }
  1511.  
  1512.     var prototypeMin = deprecate(
  1513.          'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
  1514.          function () {
  1515.              var other = local__createLocal.apply(null, arguments);
  1516.              if (this.isValid() && other.isValid()) {
  1517.                  return other < this ? this : other;
  1518.              } else {
  1519.                  return valid__createInvalid();
  1520.              }
  1521.          }
  1522.      );
  1523.  
  1524.     var prototypeMax = deprecate(
  1525.         'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
  1526.         function () {
  1527.             var other = local__createLocal.apply(null, arguments);
  1528.             if (this.isValid() && other.isValid()) {
  1529.                 return other > this ? this : other;
  1530.             } else {
  1531.                 return valid__createInvalid();
  1532.             }
  1533.         }
  1534.     );
  1535.  
  1536.     // Pick a moment m from moments so that m[fn](other) is true for all
  1537.     // other. This relies on the function fn to be transitive.
  1538.     //
  1539.     // moments should either be an array of moment objects or an array, whose
  1540.     // first element is an array of moment objects.
  1541.     function pickBy(fn, moments) {
  1542.         var res, i;
  1543.         if (moments.length === 1 && isArray(moments[0])) {
  1544.             moments = moments[0];
  1545.         }
  1546.         if (!moments.length) {
  1547.             return local__createLocal();
  1548.         }
  1549.         res = moments[0];
  1550.         for (i = 1; i < moments.length; ++i) {
  1551.             if (!moments[i].isValid() || moments[i][fn](res)) {
  1552.                 res = moments[i];
  1553.             }
  1554.         }
  1555.         return res;
  1556.     }
  1557.  
  1558.     // TODO: Use [].sort instead?
  1559.     function min () {
  1560.         var args = [].slice.call(arguments, 0);
  1561.  
  1562.         return pickBy('isBefore', args);
  1563.     }
  1564.  
  1565.     function max () {
  1566.         var args = [].slice.call(arguments, 0);
  1567.  
  1568.         return pickBy('isAfter', args);
  1569.     }
  1570.  
  1571.     var now = function () {
  1572.         return Date.now ? Date.now() : +(new Date());
  1573.     };
  1574.  
  1575.     function Duration (duration) {
  1576.         var normalizedInput = normalizeObjectUnits(duration),
  1577.             years = normalizedInput.year || 0,
  1578.             quarters = normalizedInput.quarter || 0,
  1579.             months = normalizedInput.month || 0,
  1580.             weeks = normalizedInput.week || 0,
  1581.             days = normalizedInput.day || 0,
  1582.             hours = normalizedInput.hour || 0,
  1583.             minutes = normalizedInput.minute || 0,
  1584.             seconds = normalizedInput.second || 0,
  1585.             milliseconds = normalizedInput.millisecond || 0;
  1586.  
  1587.         // representation for dateAddRemove
  1588.         this._milliseconds = +milliseconds +
  1589.             seconds * 1e3 + // 1000
  1590.             minutes * 6e4 + // 1000 * 60
  1591.             hours * 36e5; // 1000 * 60 * 60
  1592.         // Because of dateAddRemove treats 24 hours as different from a
  1593.         // day when working around DST, we need to store them separately
  1594.         this._days = +days +
  1595.             weeks * 7;
  1596.         // It is impossible translate months into days without knowing
  1597.         // which months you are are talking about, so we have to store
  1598.         // it separately.
  1599.         this._months = +months +
  1600.             quarters * 3 +
  1601.             years * 12;
  1602.  
  1603.         this._data = {};
  1604.  
  1605.         this._locale = locale_locales__getLocale();
  1606.  
  1607.         this._bubble();
  1608.     }
  1609.  
  1610.     function isDuration (obj) {
  1611.         return obj instanceof Duration;
  1612.     }
  1613.  
  1614.     // FORMATTING
  1615.  
  1616.     function offset (token, separator) {
  1617.         addFormatToken(token, 0, 0, function () {
  1618.             var offset = this.utcOffset();
  1619.             var sign = '+';
  1620.             if (offset < 0) {
  1621.                 offset = -offset;
  1622.                 sign = '-';
  1623.             }
  1624.             return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
  1625.         });
  1626.     }
  1627.  
  1628.     offset('Z', ':');
  1629.     offset('ZZ', '');
  1630.  
  1631.     // PARSING
  1632.  
  1633.     addRegexToken('Z',  matchShortOffset);
  1634.     addRegexToken('ZZ', matchShortOffset);
  1635.     addParseToken(['Z', 'ZZ'], function (input, array, config) {
  1636.         config._useUTC = true;
  1637.         config._tzm = offsetFromString(matchShortOffset, input);
  1638.     });
  1639.  
  1640.     // HELPERS
  1641.  
  1642.     // timezone chunker
  1643.     // '+10:00' > ['10',  '00']
  1644.     // '-1530'  > ['-15', '30']
  1645.     var chunkOffset = /([\+\-]|\d\d)/gi;
  1646.  
  1647.     function offsetFromString(matcher, string) {
  1648.         var matches = ((string || '').match(matcher) || []);
  1649.         var chunk   = matches[matches.length - 1] || [];
  1650.         var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
  1651.         var minutes = +(parts[1] * 60) + toInt(parts[2]);
  1652.  
  1653.         return parts[0] === '+' ? minutes : -minutes;
  1654.     }
  1655.  
  1656.     // Return a moment from input, that is local/utc/zone equivalent to model.
  1657.     function cloneWithOffset(input, model) {
  1658.         var res, diff;
  1659.         if (model._isUTC) {
  1660.             res = model.clone();
  1661.             diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);
  1662.             // Use low-level api, because this fn is low-level api.
  1663.             res._d.setTime(+res._d + diff);
  1664.             utils_hooks__hooks.updateOffset(res, false);
  1665.             return res;
  1666.         } else {
  1667.             return local__createLocal(input).local();
  1668.         }
  1669.     }
  1670.  
  1671.     function getDateOffset (m) {
  1672.         // On Firefox.24 Date#getTimezoneOffset returns a floating point.
  1673.         // https://github.com/moment/moment/pull/1871
  1674.         return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
  1675.     }
  1676.  
  1677.     // HOOKS
  1678.  
  1679.     // This function will be called whenever a moment is mutated.
  1680.     // It is intended to keep the offset in sync with the timezone.
  1681.     utils_hooks__hooks.updateOffset = function () {};
  1682.  
  1683.     // MOMENTS
  1684.  
  1685.     // keepLocalTime = true means only change the timezone, without
  1686.     // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
  1687.     // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
  1688.     // +0200, so we adjust the time as needed, to be valid.
  1689.     //
  1690.     // Keeping the time actually adds/subtracts (one hour)
  1691.     // from the actual represented time. That is why we call updateOffset
  1692.     // a second time. In case it wants us to change the offset again
  1693.     // _changeInProgress == true case, then we have to adjust, because
  1694.     // there is no such time in the given timezone.
  1695.     function getSetOffset (input, keepLocalTime) {
  1696.         var offset = this._offset || 0,
  1697.             localAdjust;
  1698.         if (!this.isValid()) {
  1699.             return input != null ? this : NaN;
  1700.         }
  1701.         if (input != null) {
  1702.             if (typeof input === 'string') {
  1703.                 input = offsetFromString(matchShortOffset, input);
  1704.             } else if (Math.abs(input) < 16) {
  1705.                 input = input * 60;
  1706.             }
  1707.             if (!this._isUTC && keepLocalTime) {
  1708.                 localAdjust = getDateOffset(this);
  1709.             }
  1710.             this._offset = input;
  1711.             this._isUTC = true;
  1712.             if (localAdjust != null) {
  1713.                 this.add(localAdjust, 'm');
  1714.             }
  1715.             if (offset !== input) {
  1716.                 if (!keepLocalTime || this._changeInProgress) {
  1717.                     add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
  1718.                 } else if (!this._changeInProgress) {
  1719.                     this._changeInProgress = true;
  1720.                     utils_hooks__hooks.updateOffset(this, true);
  1721.                     this._changeInProgress = null;
  1722.                 }
  1723.             }
  1724.             return this;
  1725.         } else {
  1726.             return this._isUTC ? offset : getDateOffset(this);
  1727.         }
  1728.     }
  1729.  
  1730.     function getSetZone (input, keepLocalTime) {
  1731.         if (input != null) {
  1732.             if (typeof input !== 'string') {
  1733.                 input = -input;
  1734.             }
  1735.  
  1736.             this.utcOffset(input, keepLocalTime);
  1737.  
  1738.             return this;
  1739.         } else {
  1740.             return -this.utcOffset();
  1741.         }
  1742.     }
  1743.  
  1744.     function setOffsetToUTC (keepLocalTime) {
  1745.         return this.utcOffset(0, keepLocalTime);
  1746.     }
  1747.  
  1748.     function setOffsetToLocal (keepLocalTime) {
  1749.         if (this._isUTC) {
  1750.             this.utcOffset(0, keepLocalTime);
  1751.             this._isUTC = false;
  1752.  
  1753.             if (keepLocalTime) {
  1754.                 this.subtract(getDateOffset(this), 'm');
  1755.             }
  1756.         }
  1757.         return this;
  1758.     }
  1759.  
  1760.     function setOffsetToParsedOffset () {
  1761.         if (this._tzm) {
  1762.             this.utcOffset(this._tzm);
  1763.         } else if (typeof this._i === 'string') {
  1764.             this.utcOffset(offsetFromString(matchOffset, this._i));
  1765.         }
  1766.         return this;
  1767.     }
  1768.  
  1769.     function hasAlignedHourOffset (input) {
  1770.         if (!this.isValid()) {
  1771.             return false;
  1772.         }
  1773.         input = input ? local__createLocal(input).utcOffset() : 0;
  1774.  
  1775.         return (this.utcOffset() - input) % 60 === 0;
  1776.     }
  1777.  
  1778.     function isDaylightSavingTime () {
  1779.         return (
  1780.             this.utcOffset() > this.clone().month(0).utcOffset() ||
  1781.             this.utcOffset() > this.clone().month(5).utcOffset()
  1782.         );
  1783.     }
  1784.  
  1785.     function isDaylightSavingTimeShifted () {
  1786.         if (!isUndefined(this._isDSTShifted)) {
  1787.             return this._isDSTShifted;
  1788.         }
  1789.  
  1790.         var c = {};
  1791.  
  1792.         copyConfig(c, this);
  1793.         c = prepareConfig(c);
  1794.  
  1795.         if (c._a) {
  1796.             var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
  1797.             this._isDSTShifted = this.isValid() &&
  1798.                 compareArrays(c._a, other.toArray()) > 0;
  1799.         } else {
  1800.             this._isDSTShifted = false;
  1801.         }
  1802.  
  1803.         return this._isDSTShifted;
  1804.     }
  1805.  
  1806.     function isLocal () {
  1807.         return this.isValid() ? !this._isUTC : false;
  1808.     }
  1809.  
  1810.     function isUtcOffset () {
  1811.         return this.isValid() ? this._isUTC : false;
  1812.     }
  1813.  
  1814.     function isUtc () {
  1815.         return this.isValid() ? this._isUTC && this._offset === 0 : false;
  1816.     }
  1817.  
  1818.     // ASP.NET json date format regex
  1819.     var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
  1820.  
  1821.     // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
  1822.     // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
  1823.     var isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;
  1824.  
  1825.     function create__createDuration (input, key) {
  1826.         var duration = input,
  1827.             // matching against regexp is expensive, do it on demand
  1828.             match = null,
  1829.             sign,
  1830.             ret,
  1831.             diffRes;
  1832.  
  1833.         if (isDuration(input)) {
  1834.             duration = {
  1835.                 ms : input._milliseconds,
  1836.                 d  : input._days,
  1837.                 M  : input._months
  1838.             };
  1839.         } else if (typeof input === 'number') {
  1840.             duration = {};
  1841.             if (key) {
  1842.                 duration[key] = input;
  1843.             } else {
  1844.                 duration.milliseconds = input;
  1845.             }
  1846.         } else if (!!(match = aspNetRegex.exec(input))) {
  1847.             sign = (match[1] === '-') ? -1 : 1;
  1848.             duration = {
  1849.                 y  : 0,
  1850.                 d  : toInt(match[DATE])        * sign,
  1851.                 h  : toInt(match[HOUR])        * sign,
  1852.                 m  : toInt(match[MINUTE])      * sign,
  1853.                 s  : toInt(match[SECOND])      * sign,
  1854.                 ms : toInt(match[MILLISECOND]) * sign
  1855.             };
  1856.         } else if (!!(match = isoRegex.exec(input))) {
  1857.             sign = (match[1] === '-') ? -1 : 1;
  1858.             duration = {
  1859.                 y : parseIso(match[2], sign),
  1860.                 M : parseIso(match[3], sign),
  1861.                 d : parseIso(match[4], sign),
  1862.                 h : parseIso(match[5], sign),
  1863.                 m : parseIso(match[6], sign),
  1864.                 s : parseIso(match[7], sign),
  1865.                 w : parseIso(match[8], sign)
  1866.             };
  1867.         } else if (duration == null) {// checks for null or undefined
  1868.             duration = {};
  1869.         } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
  1870.             diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
  1871.  
  1872.             duration = {};
  1873.             duration.ms = diffRes.milliseconds;
  1874.             duration.M = diffRes.months;
  1875.         }
  1876.  
  1877.         ret = new Duration(duration);
  1878.  
  1879.         if (isDuration(input) && hasOwnProp(input, '_locale')) {
  1880.             ret._locale = input._locale;
  1881.         }
  1882.  
  1883.         return ret;
  1884.     }
  1885.  
  1886.     create__createDuration.fn = Duration.prototype;
  1887.  
  1888.     function parseIso (inp, sign) {
  1889.         // We'd normally use ~~inp for this, but unfortunately it also
  1890.         // converts floats to ints.
  1891.         // inp may be undefined, so careful calling replace on it.
  1892.         var res = inp && parseFloat(inp.replace(',', '.'));
  1893.         // apply sign while we're at it
  1894.         return (isNaN(res) ? 0 : res) * sign;
  1895.     }
  1896.  
  1897.     function positiveMomentsDifference(base, other) {
  1898.         var res = {milliseconds: 0, months: 0};
  1899.  
  1900.         res.months = other.month() - base.month() +
  1901.             (other.year() - base.year()) * 12;
  1902.         if (base.clone().add(res.months, 'M').isAfter(other)) {
  1903.             --res.months;
  1904.         }
  1905.  
  1906.         res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
  1907.  
  1908.         return res;
  1909.     }
  1910.  
  1911.     function momentsDifference(base, other) {
  1912.         var res;
  1913.         if (!(base.isValid() && other.isValid())) {
  1914.             return {milliseconds: 0, months: 0};
  1915.         }
  1916.  
  1917.         other = cloneWithOffset(other, base);
  1918.         if (base.isBefore(other)) {
  1919.             res = positiveMomentsDifference(base, other);
  1920.         } else {
  1921.             res = positiveMomentsDifference(other, base);
  1922.             res.milliseconds = -res.milliseconds;
  1923.             res.months = -res.months;
  1924.         }
  1925.  
  1926.         return res;
  1927.     }
  1928.  
  1929.     // TODO: remove 'name' arg after deprecation is removed
  1930.     function createAdder(direction, name) {
  1931.         return function (val, period) {
  1932.             var dur, tmp;
  1933.             //invert the arguments, but complain about it
  1934.             if (period !== null && !isNaN(+period)) {
  1935.                 deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
  1936.                 tmp = val; val = period; period = tmp;
  1937.             }
  1938.  
  1939.             val = typeof val === 'string' ? +val : val;
  1940.             dur = create__createDuration(val, period);
  1941.             add_subtract__addSubtract(this, dur, direction);
  1942.             return this;
  1943.         };
  1944.     }
  1945.  
  1946.     function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
  1947.         var milliseconds = duration._milliseconds,
  1948.             days = duration._days,
  1949.             months = duration._months;
  1950.  
  1951.         if (!mom.isValid()) {
  1952.             // No op
  1953.             return;
  1954.         }
  1955.  
  1956.         updateOffset = updateOffset == null ? true : updateOffset;
  1957.  
  1958.         if (milliseconds) {
  1959.             mom._d.setTime(+mom._d + milliseconds * isAdding);
  1960.         }
  1961.         if (days) {
  1962.             get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
  1963.         }
  1964.         if (months) {
  1965.             setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
  1966.         }
  1967.         if (updateOffset) {
  1968.             utils_hooks__hooks.updateOffset(mom, days || months);
  1969.         }
  1970.     }
  1971.  
  1972.     var add_subtract__add      = createAdder(1, 'add');
  1973.     var add_subtract__subtract = createAdder(-1, 'subtract');
  1974.  
  1975.     function moment_calendar__calendar (time, formats) {
  1976.         // We want to compare the start of today, vs this.
  1977.         // Getting start-of-today depends on whether we're local/utc/offset or not.
  1978.         var now = time || local__createLocal(),
  1979.             sod = cloneWithOffset(now, this).startOf('day'),
  1980.             diff = this.diff(sod, 'days', true),
  1981.             format = diff < -6 ? 'sameElse' :
  1982.                 diff < -1 ? 'lastWeek' :
  1983.                 diff < 0 ? 'lastDay' :
  1984.                 diff < 1 ? 'sameDay' :
  1985.                 diff < 2 ? 'nextDay' :
  1986.                 diff < 7 ? 'nextWeek' : 'sameElse';
  1987.  
  1988.         var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
  1989.  
  1990.         return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
  1991.     }
  1992.  
  1993.     function clone () {
  1994.         return new Moment(this);
  1995.     }
  1996.  
  1997.     function isAfter (input, units) {
  1998.         var localInput = isMoment(input) ? input : local__createLocal(input);
  1999.         if (!(this.isValid() && localInput.isValid())) {
  2000.             return false;
  2001.         }
  2002.         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
  2003.         if (units === 'millisecond') {
  2004.             return +this > +localInput;
  2005.         } else {
  2006.             return +localInput < +this.clone().startOf(units);
  2007.         }
  2008.     }
  2009.  
  2010.     function isBefore (input, units) {
  2011.         var localInput = isMoment(input) ? input : local__createLocal(input);
  2012.         if (!(this.isValid() && localInput.isValid())) {
  2013.             return false;
  2014.         }
  2015.         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
  2016.         if (units === 'millisecond') {
  2017.             return +this < +localInput;
  2018.         } else {
  2019.             return +this.clone().endOf(units) < +localInput;
  2020.         }
  2021.     }
  2022.  
  2023.     function isBetween (from, to, units) {
  2024.         return this.isAfter(from, units) && this.isBefore(to, units);
  2025.     }
  2026.  
  2027.     function isSame (input, units) {
  2028.         var localInput = isMoment(input) ? input : local__createLocal(input),
  2029.             inputMs;
  2030.         if (!(this.isValid() && localInput.isValid())) {
  2031.             return false;
  2032.         }
  2033.         units = normalizeUnits(units || 'millisecond');
  2034.         if (units === 'millisecond') {
  2035.             return +this === +localInput;
  2036.         } else {
  2037.             inputMs = +localInput;
  2038.             return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
  2039.         }
  2040.     }
  2041.  
  2042.     function isSameOrAfter (input, units) {
  2043.         return this.isSame(input, units) || this.isAfter(input,units);
  2044.     }
  2045.  
  2046.     function isSameOrBefore (input, units) {
  2047.         return this.isSame(input, units) || this.isBefore(input,units);
  2048.     }
  2049.  
  2050.     function diff (input, units, asFloat) {
  2051.         var that,
  2052.             zoneDelta,
  2053.             delta, output;
  2054.  
  2055.         if (!this.isValid()) {
  2056.             return NaN;
  2057.         }
  2058.  
  2059.         that = cloneWithOffset(input, this);
  2060.  
  2061.         if (!that.isValid()) {
  2062.             return NaN;
  2063.         }
  2064.  
  2065.         zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
  2066.  
  2067.         units = normalizeUnits(units);
  2068.  
  2069.         if (units === 'year' || units === 'month' || units === 'quarter') {
  2070.             output = monthDiff(this, that);
  2071.             if (units === 'quarter') {
  2072.                 output = output / 3;
  2073.             } else if (units === 'year') {
  2074.                 output = output / 12;
  2075.             }
  2076.         } else {
  2077.             delta = this - that;
  2078.             output = units === 'second' ? delta / 1e3 : // 1000
  2079.                 units === 'minute' ? delta / 6e4 : // 1000 * 60
  2080.                 units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
  2081.                 units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
  2082.                 units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
  2083.                 delta;
  2084.         }
  2085.         return asFloat ? output : absFloor(output);
  2086.     }
  2087.  
  2088.     function monthDiff (a, b) {
  2089.         // difference in months
  2090.         var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
  2091.             // b is in (anchor - 1 month, anchor + 1 month)
  2092.             anchor = a.clone().add(wholeMonthDiff, 'months'),
  2093.             anchor2, adjust;
  2094.  
  2095.         if (b - anchor < 0) {
  2096.             anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
  2097.             // linear across the month
  2098.             adjust = (b - anchor) / (anchor - anchor2);
  2099.         } else {
  2100.             anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
  2101.             // linear across the month
  2102.             adjust = (b - anchor) / (anchor2 - anchor);
  2103.         }
  2104.  
  2105.         return -(wholeMonthDiff + adjust);
  2106.     }
  2107.  
  2108.     utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
  2109.  
  2110.     function toString () {
  2111.         return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
  2112.     }
  2113.  
  2114.     function moment_format__toISOString () {
  2115.         var m = this.clone().utc();
  2116.         if (0 < m.year() && m.year() <= 9999) {
  2117.             if (isFunction(Date.prototype.toISOString)) {
  2118.                 // native implementation is ~50x faster, use it when we can
  2119.                 return this.toDate().toISOString();
  2120.             } else {
  2121.                 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
  2122.             }
  2123.         } else {
  2124.             return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
  2125.         }
  2126.     }
  2127.  
  2128.     function format (inputString) {
  2129.         var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);
  2130.         return this.localeData().postformat(output);
  2131.     }
  2132.  
  2133.     function from (time, withoutSuffix) {
  2134.         if (this.isValid() &&
  2135.                 ((isMoment(time) && time.isValid()) ||
  2136.                  local__createLocal(time).isValid())) {
  2137.             return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
  2138.         } else {
  2139.             return this.localeData().invalidDate();
  2140.         }
  2141.     }
  2142.  
  2143.     function fromNow (withoutSuffix) {
  2144.         return this.from(local__createLocal(), withoutSuffix);
  2145.     }
  2146.  
  2147.     function to (time, withoutSuffix) {
  2148.         if (this.isValid() &&
  2149.                 ((isMoment(time) && time.isValid()) ||
  2150.                  local__createLocal(time).isValid())) {
  2151.             return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
  2152.         } else {
  2153.             return this.localeData().invalidDate();
  2154.         }
  2155.     }
  2156.  
  2157.     function toNow (withoutSuffix) {
  2158.         return this.to(local__createLocal(), withoutSuffix);
  2159.     }
  2160.  
  2161.     // If passed a locale key, it will set the locale for this
  2162.     // instance.  Otherwise, it will return the locale configuration
  2163.     // variables for this instance.
  2164.     function locale (key) {
  2165.         var newLocaleData;
  2166.  
  2167.         if (key === undefined) {
  2168.             return this._locale._abbr;
  2169.         } else {
  2170.             newLocaleData = locale_locales__getLocale(key);
  2171.             if (newLocaleData != null) {
  2172.                 this._locale = newLocaleData;
  2173.             }
  2174.             return this;
  2175.         }
  2176.     }
  2177.  
  2178.     var lang = deprecate(
  2179.         'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
  2180.         function (key) {
  2181.             if (key === undefined) {
  2182.                 return this.localeData();
  2183.             } else {
  2184.                 return this.locale(key);
  2185.             }
  2186.         }
  2187.     );
  2188.  
  2189.     function localeData () {
  2190.         return this._locale;
  2191.     }
  2192.  
  2193.     function startOf (units) {
  2194.         units = normalizeUnits(units);
  2195.         // the following switch intentionally omits break keywords
  2196.         // to utilize falling through the cases.
  2197.         switch (units) {
  2198.         case 'year':
  2199.             this.month(0);
  2200.             /* falls through */
  2201.         case 'quarter':
  2202.         case 'month':
  2203.             this.date(1);
  2204.             /* falls through */
  2205.         case 'week':
  2206.         case 'isoWeek':
  2207.         case 'day':
  2208.             this.hours(0);
  2209.             /* falls through */
  2210.         case 'hour':
  2211.             this.minutes(0);
  2212.             /* falls through */
  2213.         case 'minute':
  2214.             this.seconds(0);
  2215.             /* falls through */
  2216.         case 'second':
  2217.             this.milliseconds(0);
  2218.         }
  2219.  
  2220.         // weeks are a special case
  2221.         if (units === 'week') {
  2222.             this.weekday(0);
  2223.         }
  2224.         if (units === 'isoWeek') {
  2225.             this.isoWeekday(1);
  2226.         }
  2227.  
  2228.         // quarters are also special
  2229.         if (units === 'quarter') {
  2230.             this.month(Math.floor(this.month() / 3) * 3);
  2231.         }
  2232.  
  2233.         return this;
  2234.     }
  2235.  
  2236.     function endOf (units) {
  2237.         units = normalizeUnits(units);
  2238.         if (units === undefined || units === 'millisecond') {
  2239.             return this;
  2240.         }
  2241.         return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
  2242.     }
  2243.  
  2244.     function to_type__valueOf () {
  2245.         return +this._d - ((this._offset || 0) * 60000);
  2246.     }
  2247.  
  2248.     function unix () {
  2249.         return Math.floor(+this / 1000);
  2250.     }
  2251.  
  2252.     function toDate () {
  2253.         return this._offset ? new Date(+this) : this._d;
  2254.     }
  2255.  
  2256.     function toArray () {
  2257.         var m = this;
  2258.         return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
  2259.     }
  2260.  
  2261.     function toObject () {
  2262.         var m = this;
  2263.         return {
  2264.             years: m.year(),
  2265.             months: m.month(),
  2266.             date: m.date(),
  2267.             hours: m.hours(),
  2268.             minutes: m.minutes(),
  2269.             seconds: m.seconds(),
  2270.             milliseconds: m.milliseconds()
  2271.         };
  2272.     }
  2273.  
  2274.     function toJSON () {
  2275.         // JSON.stringify(new Date(NaN)) === 'null'
  2276.         return this.isValid() ? this.toISOString() : 'null';
  2277.     }
  2278.  
  2279.     function moment_valid__isValid () {
  2280.         return valid__isValid(this);
  2281.     }
  2282.  
  2283.     function parsingFlags () {
  2284.         return extend({}, getParsingFlags(this));
  2285.     }
  2286.  
  2287.     function invalidAt () {
  2288.         return getParsingFlags(this).overflow;
  2289.     }
  2290.  
  2291.     function creationData() {
  2292.         return {
  2293.             input: this._i,
  2294.             format: this._f,
  2295.             locale: this._locale,
  2296.             isUTC: this._isUTC,
  2297.             strict: this._strict
  2298.         };
  2299.     }
  2300.  
  2301.     // FORMATTING
  2302.  
  2303.     addFormatToken(0, ['gg', 2], 0, function () {
  2304.         return this.weekYear() % 100;
  2305.     });
  2306.  
  2307.     addFormatToken(0, ['GG', 2], 0, function () {
  2308.         return this.isoWeekYear() % 100;
  2309.     });
  2310.  
  2311.     function addWeekYearFormatToken (token, getter) {
  2312.         addFormatToken(0, [token, token.length], 0, getter);
  2313.     }
  2314.  
  2315.     addWeekYearFormatToken('gggg',     'weekYear');
  2316.     addWeekYearFormatToken('ggggg',    'weekYear');
  2317.     addWeekYearFormatToken('GGGG',  'isoWeekYear');
  2318.     addWeekYearFormatToken('GGGGG', 'isoWeekYear');
  2319.  
  2320.     // ALIASES
  2321.  
  2322.     addUnitAlias('weekYear', 'gg');
  2323.     addUnitAlias('isoWeekYear', 'GG');
  2324.  
  2325.     // PARSING
  2326.  
  2327.     addRegexToken('G',      matchSigned);
  2328.     addRegexToken('g',      matchSigned);
  2329.     addRegexToken('GG',     match1to2, match2);
  2330.     addRegexToken('gg',     match1to2, match2);
  2331.     addRegexToken('GGGG',   match1to4, match4);
  2332.     addRegexToken('gggg',   match1to4, match4);
  2333.     addRegexToken('GGGGG',  match1to6, match6);
  2334.     addRegexToken('ggggg',  match1to6, match6);
  2335.  
  2336.     addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
  2337.         week[token.substr(0, 2)] = toInt(input);
  2338.     });
  2339.  
  2340.     addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
  2341.         week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
  2342.     });
  2343.  
  2344.     // MOMENTS
  2345.  
  2346.     function getSetWeekYear (input) {
  2347.         return getSetWeekYearHelper.call(this,
  2348.                 input,
  2349.                 this.week(),
  2350.                 this.weekday(),
  2351.                 this.localeData()._week.dow,
  2352.                 this.localeData()._week.doy);
  2353.     }
  2354.  
  2355.     function getSetISOWeekYear (input) {
  2356.         return getSetWeekYearHelper.call(this,
  2357.                 input, this.isoWeek(), this.isoWeekday(), 1, 4);
  2358.     }
  2359.  
  2360.     function getISOWeeksInYear () {
  2361.         return weeksInYear(this.year(), 1, 4);
  2362.     }
  2363.  
  2364.     function getWeeksInYear () {
  2365.         var weekInfo = this.localeData()._week;
  2366.         return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
  2367.     }
  2368.  
  2369.     function getSetWeekYearHelper(input, week, weekday, dow, doy) {
  2370.         var weeksTarget;
  2371.         if (input == null) {
  2372.             return weekOfYear(this, dow, doy).year;
  2373.         } else {
  2374.             weeksTarget = weeksInYear(input, dow, doy);
  2375.             if (week > weeksTarget) {
  2376.                 week = weeksTarget;
  2377.             }
  2378.             return setWeekAll.call(this, input, week, weekday, dow, doy);
  2379.         }
  2380.     }
  2381.  
  2382.     function setWeekAll(weekYear, week, weekday, dow, doy) {
  2383.         var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
  2384.             date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
  2385.  
  2386.         // console.log("got", weekYear, week, weekday, "set", date.toISOString());
  2387.         this.year(date.getUTCFullYear());
  2388.         this.month(date.getUTCMonth());
  2389.         this.date(date.getUTCDate());
  2390.         return this;
  2391.     }
  2392.  
  2393.     // FORMATTING
  2394.  
  2395.     addFormatToken('Q', 0, 'Qo', 'quarter');
  2396.  
  2397.     // ALIASES
  2398.  
  2399.     addUnitAlias('quarter', 'Q');
  2400.  
  2401.     // PARSING
  2402.  
  2403.     addRegexToken('Q', match1);
  2404.     addParseToken('Q', function (input, array) {
  2405.         array[MONTH] = (toInt(input) - 1) * 3;
  2406.     });
  2407.  
  2408.     // MOMENTS
  2409.  
  2410.     function getSetQuarter (input) {
  2411.         return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
  2412.     }
  2413.  
  2414.     // FORMATTING
  2415.  
  2416.     addFormatToken('w', ['ww', 2], 'wo', 'week');
  2417.     addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
  2418.  
  2419.     // ALIASES
  2420.  
  2421.     addUnitAlias('week', 'w');
  2422.     addUnitAlias('isoWeek', 'W');
  2423.  
  2424.     // PARSING
  2425.  
  2426.     addRegexToken('w',  match1to2);
  2427.     addRegexToken('ww', match1to2, match2);
  2428.     addRegexToken('W',  match1to2);
  2429.     addRegexToken('WW', match1to2, match2);
  2430.  
  2431.     addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
  2432.         week[token.substr(0, 1)] = toInt(input);
  2433.     });
  2434.  
  2435.     // HELPERS
  2436.  
  2437.     // LOCALES
  2438.  
  2439.     function localeWeek (mom) {
  2440.         return weekOfYear(mom, this._week.dow, this._week.doy).week;
  2441.     }
  2442.  
  2443.     var defaultLocaleWeek = {
  2444.         dow : 0, // Sunday is the first day of the week.
  2445.         doy : 6  // The week that contains Jan 1st is the first week of the year.
  2446.     };
  2447.  
  2448.     function localeFirstDayOfWeek () {
  2449.         return this._week.dow;
  2450.     }
  2451.  
  2452.     function localeFirstDayOfYear () {
  2453.         return this._week.doy;
  2454.     }
  2455.  
  2456.     // MOMENTS
  2457.  
  2458.     function getSetWeek (input) {
  2459.         var week = this.localeData().week(this);
  2460.         return input == null ? week : this.add((input - week) * 7, 'd');
  2461.     }
  2462.  
  2463.     function getSetISOWeek (input) {
  2464.         var week = weekOfYear(this, 1, 4).week;
  2465.         return input == null ? week : this.add((input - week) * 7, 'd');
  2466.     }
  2467.  
  2468.     // FORMATTING
  2469.  
  2470.     addFormatToken('D', ['DD', 2], 'Do', 'date');
  2471.  
  2472.     // ALIASES
  2473.  
  2474.     addUnitAlias('date', 'D');
  2475.  
  2476.     // PARSING
  2477.  
  2478.     addRegexToken('D',  match1to2);
  2479.     addRegexToken('DD', match1to2, match2);
  2480.     addRegexToken('Do', function (isStrict, locale) {
  2481.         return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
  2482.     });
  2483.  
  2484.     addParseToken(['D', 'DD'], DATE);
  2485.     addParseToken('Do', function (input, array) {
  2486.         array[DATE] = toInt(input.match(match1to2)[0], 10);
  2487.     });
  2488.  
  2489.     // MOMENTS
  2490.  
  2491.     var getSetDayOfMonth = makeGetSet('Date', true);
  2492.  
  2493.     // FORMATTING
  2494.  
  2495.     addFormatToken('d', 0, 'do', 'day');
  2496.  
  2497.     addFormatToken('dd', 0, 0, function (format) {
  2498.         return this.localeData().weekdaysMin(this, format);
  2499.     });
  2500.  
  2501.     addFormatToken('ddd', 0, 0, function (format) {
  2502.         return this.localeData().weekdaysShort(this, format);
  2503.     });
  2504.  
  2505.     addFormatToken('dddd', 0, 0, function (format) {
  2506.         return this.localeData().weekdays(this, format);
  2507.     });
  2508.  
  2509.     addFormatToken('e', 0, 0, 'weekday');
  2510.     addFormatToken('E', 0, 0, 'isoWeekday');
  2511.  
  2512.     // ALIASES
  2513.  
  2514.     addUnitAlias('day', 'd');
  2515.     addUnitAlias('weekday', 'e');
  2516.     addUnitAlias('isoWeekday', 'E');
  2517.  
  2518.     // PARSING
  2519.  
  2520.     addRegexToken('d',    match1to2);
  2521.     addRegexToken('e',    match1to2);
  2522.     addRegexToken('E',    match1to2);
  2523.     addRegexToken('dd',   matchWord);
  2524.     addRegexToken('ddd',  matchWord);
  2525.     addRegexToken('dddd', matchWord);
  2526.  
  2527.     addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
  2528.         var weekday = config._locale.weekdaysParse(input, token, config._strict);
  2529.         // if we didn't get a weekday name, mark the date as invalid
  2530.         if (weekday != null) {
  2531.             week.d = weekday;
  2532.         } else {
  2533.             getParsingFlags(config).invalidWeekday = input;
  2534.         }
  2535.     });
  2536.  
  2537.     addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
  2538.         week[token] = toInt(input);
  2539.     });
  2540.  
  2541.     // HELPERS
  2542.  
  2543.     function parseWeekday(input, locale) {
  2544.         if (typeof input !== 'string') {
  2545.             return input;
  2546.         }
  2547.  
  2548.         if (!isNaN(input)) {
  2549.             return parseInt(input, 10);
  2550.         }
  2551.  
  2552.         input = locale.weekdaysParse(input);
  2553.         if (typeof input === 'number') {
  2554.             return input;
  2555.         }
  2556.  
  2557.         return null;
  2558.     }
  2559.  
  2560.     // LOCALES
  2561.  
  2562.     var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
  2563.     function localeWeekdays (m, format) {
  2564.         return isArray(this._weekdays) ? this._weekdays[m.day()] :
  2565.             this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
  2566.     }
  2567.  
  2568.     var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
  2569.     function localeWeekdaysShort (m) {
  2570.         return this._weekdaysShort[m.day()];
  2571.     }
  2572.  
  2573.     var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
  2574.     function localeWeekdaysMin (m) {
  2575.         return this._weekdaysMin[m.day()];
  2576.     }
  2577.  
  2578.     function localeWeekdaysParse (weekdayName, format, strict) {
  2579.         var i, mom, regex;
  2580.  
  2581.         if (!this._weekdaysParse) {
  2582.             this._weekdaysParse = [];
  2583.             this._minWeekdaysParse = [];
  2584.             this._shortWeekdaysParse = [];
  2585.             this._fullWeekdaysParse = [];
  2586.         }
  2587.  
  2588.         for (i = 0; i < 7; i++) {
  2589.             // make the regex if we don't have it already
  2590.  
  2591.             mom = local__createLocal([2000, 1]).day(i);
  2592.             if (strict && !this._fullWeekdaysParse[i]) {
  2593.                 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
  2594.                 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
  2595.                 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
  2596.             }
  2597.             if (!this._weekdaysParse[i]) {
  2598.                 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
  2599.                 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
  2600.             }
  2601.             // test the regex
  2602.             if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
  2603.                 return i;
  2604.             } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
  2605.                 return i;
  2606.             } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
  2607.                 return i;
  2608.             } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
  2609.                 return i;
  2610.             }
  2611.         }
  2612.     }
  2613.  
  2614.     // MOMENTS
  2615.  
  2616.     function getSetDayOfWeek (input) {
  2617.         if (!this.isValid()) {
  2618.             return input != null ? this : NaN;
  2619.         }
  2620.         var day =