Skip to:
Content

BuddyPress.org

Changeset 11190


Ignore:
Timestamp:
10/12/2016 11:09:46 PM (8 years ago)
Author:
r-a-y
Message:

Core: Update moment.js to v2.15.1.

We're also moving the file to the /vendor/moment-js/ directory, which
will be used to house all of the locale files for moment.js in a
subsequent commit.

See #7275.

Location:
trunk/src/bp-core
Files:
1 added
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/bp-core-cssjs.php

    r11013 r11190  
    4949
    5050        // Version 2.7.
    51         'bp-moment'    => array( 'file' => "{$url}vendor/moment{$min}.js", 'dependencies' => array(), 'footer' => true ),
     51        'bp-moment'    => array( 'file' => "{$url}vendor/moment-js/moment{$min}.js", 'dependencies' => array(), 'footer' => true ),
    5252        'bp-livestamp' => array( 'file' => "{$url}vendor/livestamp{$min}.js", 'dependencies' => array( 'jquery', 'bp-moment' ), 'footer' => true ),
    5353    ) );
  • trunk/src/bp-core/js/vendor/moment-js/moment.js

    r11189 r11190  
    11//! moment.js
    2 //! version : 2.13.0
     2//! version : 2.15.1
    33//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
    44//! license : MIT
     
    2525    function isArray(input) {
    2626        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
     27    }
     28
     29    function isObject(input) {
     30        // IE8 will treat undefined and null as object if it wasn't for
     31        // input != null
     32        return input != null && Object.prototype.toString.call(input) === '[object Object]';
     33    }
     34
     35    function isObjectEmpty(obj) {
     36        var k;
     37        for (k in obj) {
     38            // even if its not own property I'd still call it non-empty
     39            return false;
     40        }
     41        return true;
    2742    }
    2843
     
    114129                return i != null;
    115130            });
    116             m._isValid = !isNaN(m._d.getTime()) &&
     131            var isNowValid = !isNaN(m._d.getTime()) &&
    117132                flags.overflow < 0 &&
    118133                !flags.empty &&
     
    125140
    126141            if (m._strict) {
    127                 m._isValid = m._isValid &&
     142                isNowValid = isNowValid &&
    128143                    flags.charsLeftOver === 0 &&
    129144                    flags.unusedTokens.length === 0 &&
    130145                    flags.bigHour === undefined;
     146            }
     147
     148            if (Object.isFrozen == null || !Object.isFrozen(m)) {
     149                m._isValid = isNowValid;
     150            }
     151            else {
     152                return isNowValid;
    131153            }
    132154        }
     
    222244    function absFloor (number) {
    223245        if (number < 0) {
    224             return Math.ceil(number);
     246            // -0 -> 0
     247            return Math.ceil(number) || 0;
    225248        } else {
    226249            return Math.floor(number);
     
    269292            }
    270293            if (firstTime) {
    271                 warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
     294                var args = [];
     295                var arg;
     296                for (var i = 0; i < arguments.length; i++) {
     297                    arg = '';
     298                    if (typeof arguments[i] === 'object') {
     299                        arg += '\n[' + i + '] ';
     300                        for (var key in arguments[0]) {
     301                            arg += key + ': ' + arguments[0][key] + ', ';
     302                        }
     303                        arg = arg.slice(0, -2); // Remove trailing comma and space
     304                    } else {
     305                        arg = arguments[i];
     306                    }
     307                    args.push(arg);
     308                }
     309                warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
    272310                firstTime = false;
    273311            }
     
    293331    function isFunction(input) {
    294332        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
    295     }
    296 
    297     function isObject(input) {
    298         return Object.prototype.toString.call(input) === '[object Object]';
    299333    }
    300334
     
    330364            }
    331365        }
     366        for (prop in parentConfig) {
     367            if (hasOwnProp(parentConfig, prop) &&
     368                    !hasOwnProp(childConfig, prop) &&
     369                    isObject(parentConfig[prop])) {
     370                // make sure changes to properties don't modify parent config
     371                res[prop] = extend({}, res[prop]);
     372            }
     373        }
    332374        return res;
    333375    }
     
    355397    }
    356398
    357     // internal storage for locale config files
    358     var locales = {};
    359     var globalLocale;
    360 
    361     function normalizeLocale(key) {
    362         return key ? key.toLowerCase().replace('_', '-') : key;
    363     }
    364 
    365     // pick the locale from the array
    366     // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
    367     // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
    368     function chooseLocale(names) {
    369         var i = 0, j, next, locale, split;
    370 
    371         while (i < names.length) {
    372             split = normalizeLocale(names[i]).split('-');
    373             j = split.length;
    374             next = normalizeLocale(names[i + 1]);
    375             next = next ? next.split('-') : null;
    376             while (j > 0) {
    377                 locale = loadLocale(split.slice(0, j).join('-'));
    378                 if (locale) {
    379                     return locale;
    380                 }
    381                 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
    382                     //the next array item is better than a shallower substring of this one
    383                     break;
    384                 }
    385                 j--;
    386             }
    387             i++;
    388         }
    389         return null;
    390     }
    391 
    392     function loadLocale(name) {
    393         var oldLocale = null;
    394         // TODO: Find a better way to register and load all the locales in Node
    395         if (!locales[name] && (typeof module !== 'undefined') &&
    396                 module && module.exports) {
    397             try {
    398                 oldLocale = globalLocale._abbr;
    399                 require('./locale/' + name);
    400                 // because defineLocale currently also sets the global locale, we
    401                 // want to undo that for lazy loaded locales
    402                 locale_locales__getSetGlobalLocale(oldLocale);
    403             } catch (e) { }
    404         }
    405         return locales[name];
    406     }
    407 
    408     // This function will load locale and then set the global locale.  If
    409     // no arguments are passed in, it will simply return the current global
    410     // locale key.
    411     function locale_locales__getSetGlobalLocale (key, values) {
    412         var data;
    413         if (key) {
    414             if (isUndefined(values)) {
    415                 data = locale_locales__getLocale(key);
    416             }
    417             else {
    418                 data = defineLocale(key, values);
    419             }
    420 
    421             if (data) {
    422                 // moment.duration._locale = moment._locale = data;
    423                 globalLocale = data;
    424             }
    425         }
    426 
    427         return globalLocale._abbr;
    428     }
    429 
    430     function defineLocale (name, config) {
    431         if (config !== null) {
    432             config.abbr = name;
    433             if (locales[name] != null) {
    434                 deprecateSimple('defineLocaleOverride',
    435                         'use moment.updateLocale(localeName, config) to change ' +
    436                         'an existing locale. moment.defineLocale(localeName, ' +
    437                         'config) should only be used for creating a new locale');
    438                 config = mergeConfigs(locales[name]._config, config);
    439             } else if (config.parentLocale != null) {
    440                 if (locales[config.parentLocale] != null) {
    441                     config = mergeConfigs(locales[config.parentLocale]._config, config);
    442                 } else {
    443                     // treat as if there is no base config
    444                     deprecateSimple('parentLocaleUndefined',
    445                             'specified parentLocale is not defined yet');
    446                 }
    447             }
    448             locales[name] = new Locale(config);
    449 
    450             // backwards compat for now: also set the locale
    451             locale_locales__getSetGlobalLocale(name);
    452 
    453             return locales[name];
    454         } else {
    455             // useful for testing
    456             delete locales[name];
    457             return null;
    458         }
    459     }
    460 
    461     function updateLocale(name, config) {
    462         if (config != null) {
    463             var locale;
    464             if (locales[name] != null) {
    465                 config = mergeConfigs(locales[name]._config, config);
    466             }
    467             locale = new Locale(config);
    468             locale.parentLocale = locales[name];
    469             locales[name] = locale;
    470 
    471             // backwards compat for now: also set the locale
    472             locale_locales__getSetGlobalLocale(name);
    473         } else {
    474             // pass null for config to unupdate, useful for tests
    475             if (locales[name] != null) {
    476                 if (locales[name].parentLocale != null) {
    477                     locales[name] = locales[name].parentLocale;
    478                 } else if (locales[name] != null) {
    479                     delete locales[name];
    480                 }
    481             }
    482         }
    483         return locales[name];
    484     }
    485 
    486     // returns locale data
    487     function locale_locales__getLocale (key) {
    488         var locale;
    489 
    490         if (key && key._locale && key._locale._abbr) {
    491             key = key._locale._abbr;
    492         }
    493 
    494         if (!key) {
    495             return globalLocale;
    496         }
    497 
    498         if (!isArray(key)) {
    499             //short-circuit everything else
    500             locale = loadLocale(key);
    501             if (locale) {
    502                 return locale;
    503             }
    504             key = [key];
    505         }
    506 
    507         return chooseLocale(key);
    508     }
    509 
    510     function locale_locales__listLocales() {
    511         return keys(locales);
     399    var defaultCalendar = {
     400        sameDay : '[Today at] LT',
     401        nextDay : '[Tomorrow at] LT',
     402        nextWeek : 'dddd [at] LT',
     403        lastDay : '[Yesterday at] LT',
     404        lastWeek : '[Last] dddd [at] LT',
     405        sameElse : 'L'
     406    };
     407
     408    function locale_calendar__calendar (key, mom, now) {
     409        var output = this._calendar[key] || this._calendar['sameElse'];
     410        return isFunction(output) ? output.call(mom, now) : output;
     411    }
     412
     413    var defaultLongDateFormat = {
     414        LTS  : 'h:mm:ss A',
     415        LT   : 'h:mm A',
     416        L    : 'MM/DD/YYYY',
     417        LL   : 'MMMM D, YYYY',
     418        LLL  : 'MMMM D, YYYY h:mm A',
     419        LLLL : 'dddd, MMMM D, YYYY h:mm A'
     420    };
     421
     422    function longDateFormat (key) {
     423        var format = this._longDateFormat[key],
     424            formatUpper = this._longDateFormat[key.toUpperCase()];
     425
     426        if (format || !formatUpper) {
     427            return format;
     428        }
     429
     430        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
     431            return val.slice(1);
     432        });
     433
     434        return this._longDateFormat[key];
     435    }
     436
     437    var defaultInvalidDate = 'Invalid date';
     438
     439    function invalidDate () {
     440        return this._invalidDate;
     441    }
     442
     443    var defaultOrdinal = '%d';
     444    var defaultOrdinalParse = /\d{1,2}/;
     445
     446    function ordinal (number) {
     447        return this._ordinal.replace('%d', number);
     448    }
     449
     450    var defaultRelativeTime = {
     451        future : 'in %s',
     452        past   : '%s ago',
     453        s  : 'a few seconds',
     454        m  : 'a minute',
     455        mm : '%d minutes',
     456        h  : 'an hour',
     457        hh : '%d hours',
     458        d  : 'a day',
     459        dd : '%d days',
     460        M  : 'a month',
     461        MM : '%d months',
     462        y  : 'a year',
     463        yy : '%d years'
     464    };
     465
     466    function relative__relativeTime (number, withoutSuffix, string, isFuture) {
     467        var output = this._relativeTime[string];
     468        return (isFunction(output)) ?
     469            output(number, withoutSuffix, string, isFuture) :
     470            output.replace(/%d/i, number);
     471    }
     472
     473    function pastFuture (diff, output) {
     474        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
     475        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
    512476    }
    513477
     
    538502
    539503        return normalizedInput;
     504    }
     505
     506    var priorities = {};
     507
     508    function addUnitPriority(unit, priority) {
     509        priorities[unit] = priority;
     510    }
     511
     512    function getPrioritizedUnits(unitsObj) {
     513        var units = [];
     514        for (var u in unitsObj) {
     515            units.push({unit: u, priority: priorities[u]});
     516        }
     517        units.sort(function (a, b) {
     518            return a.priority - b.priority;
     519        });
     520        return units;
    540521    }
    541522
     
    565546    // MOMENTS
    566547
    567     function getSet (units, value) {
    568         var unit;
     548    function stringGet (units) {
     549        units = normalizeUnits(units);
     550        if (isFunction(this[units])) {
     551            return this[units]();
     552        }
     553        return this;
     554    }
     555
     556
     557    function stringSet (units, value) {
    569558        if (typeof units === 'object') {
    570             for (unit in units) {
    571                 this.set(unit, units[unit]);
     559            units = normalizeObjectUnits(units);
     560            var prioritized = getPrioritizedUnits(units);
     561            for (var i = 0; i < prioritized.length; i++) {
     562                this[prioritized[i].unit](units[prioritized[i].unit]);
    572563            }
    573564        } else {
     
    809800    addUnitAlias('month', 'M');
    810801
     802    // PRIORITY
     803
     804    addUnitPriority('month', 8);
     805
    811806    // PARSING
    812807
     
    839834    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
    840835    function localeMonths (m, format) {
     836        if (!m) {
     837            return this._months;
     838        }
    841839        return isArray(this._months) ? this._months[m.month()] :
    842             this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
     840            this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
    843841    }
    844842
    845843    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
    846844    function localeMonthsShort (m, format) {
     845        if (!m) {
     846            return this._monthsShort;
     847        }
    847848        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
    848849            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
     
    981982            }
    982983        } else {
     984            if (!hasOwnProp(this, '_monthsShortRegex')) {
     985                this._monthsShortRegex = defaultMonthsShortRegex;
     986            }
    983987            return this._monthsShortStrictRegex && isStrict ?
    984988                this._monthsShortStrictRegex : this._monthsShortRegex;
     
    9981002            }
    9991003        } else {
     1004            if (!hasOwnProp(this, '_monthsRegex')) {
     1005                this._monthsRegex = defaultMonthsRegex;
     1006            }
    10001007            return this._monthsStrictRegex && isStrict ?
    10011008                this._monthsStrictRegex : this._monthsRegex;
     
    10261033            shortPieces[i] = regexEscape(shortPieces[i]);
    10271034            longPieces[i] = regexEscape(longPieces[i]);
     1035        }
     1036        for (i = 0; i < 24; i++) {
    10281037            mixedPieces[i] = regexEscape(mixedPieces[i]);
    10291038        }
     
    10351044    }
    10361045
    1037     function checkOverflow (m) {
    1038         var overflow;
    1039         var a = m._a;
    1040 
    1041         if (a && getParsingFlags(m).overflow === -2) {
    1042             overflow =
    1043                 a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
    1044                 a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
    1045                 a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
    1046                 a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
    1047                 a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
    1048                 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
    1049                 -1;
    1050 
    1051             if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
    1052                 overflow = DATE;
    1053             }
    1054             if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
    1055                 overflow = WEEK;
    1056             }
    1057             if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
    1058                 overflow = WEEKDAY;
    1059             }
    1060 
    1061             getParsingFlags(m).overflow = overflow;
    1062         }
    1063 
    1064         return m;
    1065     }
    1066 
    1067     // iso 8601 regex
    1068     // 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)
    1069     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)?)?/;
    1070     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)?)?/;
    1071 
    1072     var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
    1073 
    1074     var isoDates = [
    1075         ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
    1076         ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
    1077         ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
    1078         ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
    1079         ['YYYY-DDD', /\d{4}-\d{3}/],
    1080         ['YYYY-MM', /\d{4}-\d\d/, false],
    1081         ['YYYYYYMMDD', /[+-]\d{10}/],
    1082         ['YYYYMMDD', /\d{8}/],
    1083         // YYYYMM is NOT allowed by the standard
    1084         ['GGGG[W]WWE', /\d{4}W\d{3}/],
    1085         ['GGGG[W]WW', /\d{4}W\d{2}/, false],
    1086         ['YYYYDDD', /\d{7}/]
    1087     ];
    1088 
    1089     // iso time formats and regexes
    1090     var isoTimes = [
    1091         ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
    1092         ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
    1093         ['HH:mm:ss', /\d\d:\d\d:\d\d/],
    1094         ['HH:mm', /\d\d:\d\d/],
    1095         ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
    1096         ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
    1097         ['HHmmss', /\d\d\d\d\d\d/],
    1098         ['HHmm', /\d\d\d\d/],
    1099         ['HH', /\d\d/]
    1100     ];
    1101 
    1102     var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
    1103 
    1104     // date from iso format
    1105     function configFromISO(config) {
    1106         var i, l,
    1107             string = config._i,
    1108             match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
    1109             allowTime, dateFormat, timeFormat, tzFormat;
    1110 
    1111         if (match) {
    1112             getParsingFlags(config).iso = true;
    1113 
    1114             for (i = 0, l = isoDates.length; i < l; i++) {
    1115                 if (isoDates[i][1].exec(match[1])) {
    1116                     dateFormat = isoDates[i][0];
    1117                     allowTime = isoDates[i][2] !== false;
    1118                     break;
    1119                 }
    1120             }
    1121             if (dateFormat == null) {
    1122                 config._isValid = false;
    1123                 return;
    1124             }
    1125             if (match[3]) {
    1126                 for (i = 0, l = isoTimes.length; i < l; i++) {
    1127                     if (isoTimes[i][1].exec(match[3])) {
    1128                         // match[2] should be 'T' or space
    1129                         timeFormat = (match[2] || ' ') + isoTimes[i][0];
    1130                         break;
    1131                     }
    1132                 }
    1133                 if (timeFormat == null) {
    1134                     config._isValid = false;
    1135                     return;
    1136                 }
    1137             }
    1138             if (!allowTime && timeFormat != null) {
    1139                 config._isValid = false;
    1140                 return;
    1141             }
    1142             if (match[4]) {
    1143                 if (tzRegex.exec(match[4])) {
    1144                     tzFormat = 'Z';
    1145                 } else {
    1146                     config._isValid = false;
    1147                     return;
    1148                 }
    1149             }
    1150             config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
    1151             configFromStringAndFormat(config);
    1152         } else {
    1153             config._isValid = false;
    1154         }
    1155     }
    1156 
    1157     // date from iso format or fallback
    1158     function configFromString(config) {
    1159         var matched = aspNetJsonRegex.exec(config._i);
    1160 
    1161         if (matched !== null) {
    1162             config._d = new Date(+matched[1]);
    1163             return;
    1164         }
    1165 
    1166         configFromISO(config);
    1167         if (config._isValid === false) {
    1168             delete config._isValid;
    1169             utils_hooks__hooks.createFromInputFallback(config);
    1170         }
    1171     }
    1172 
    1173     utils_hooks__hooks.createFromInputFallback = deprecate(
    1174         'moment construction falls back to js Date. This is ' +
    1175         'discouraged and will be removed in upcoming major ' +
    1176         'release. Please refer to ' +
    1177         'https://github.com/moment/moment/issues/1407 for more info.',
    1178         function (config) {
    1179             config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
    1180         }
    1181     );
    1182 
    1183     function createDate (y, m, d, h, M, s, ms) {
    1184         //can't just apply() to create a date:
    1185         //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
    1186         var date = new Date(y, m, d, h, M, s, ms);
    1187 
    1188         //the date constructor remaps years 0-99 to 1900-1999
    1189         if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
    1190             date.setFullYear(y);
    1191         }
    1192         return date;
    1193     }
    1194 
    1195     function createUTCDate (y) {
    1196         var date = new Date(Date.UTC.apply(null, arguments));
    1197 
    1198         //the Date.UTC function remaps years 0-99 to 1900-1999
    1199         if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
    1200             date.setUTCFullYear(y);
    1201         }
    1202         return date;
    1203     }
    1204 
    12051046    // FORMATTING
    12061047
     
    12211062
    12221063    addUnitAlias('year', 'y');
     1064
     1065    // PRIORITIES
     1066
     1067    addUnitPriority('year', 1);
    12231068
    12241069    // PARSING
     
    12631108    function getIsLeapYear () {
    12641109        return isLeapYear(this.year());
     1110    }
     1111
     1112    function createDate (y, m, d, h, M, s, ms) {
     1113        //can't just apply() to create a date:
     1114        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
     1115        var date = new Date(y, m, d, h, M, s, ms);
     1116
     1117        //the date constructor remaps years 0-99 to 1900-1999
     1118        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
     1119            date.setFullYear(y);
     1120        }
     1121        return date;
     1122    }
     1123
     1124    function createUTCDate (y) {
     1125        var date = new Date(Date.UTC.apply(null, arguments));
     1126
     1127        //the Date.UTC function remaps years 0-99 to 1900-1999
     1128        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
     1129            date.setUTCFullYear(y);
     1130        }
     1131        return date;
    12651132    }
    12661133
     
    13271194    }
    13281195
    1329     // Pick the first defined of two or three arguments.
    1330     function defaults(a, b, c) {
    1331         if (a != null) {
    1332             return a;
    1333         }
    1334         if (b != null) {
    1335             return b;
    1336         }
    1337         return c;
    1338     }
    1339 
    1340     function currentDateArray(config) {
    1341         // hooks is actually the exported moment object
    1342         var nowValue = new Date(utils_hooks__hooks.now());
    1343         if (config._useUTC) {
    1344             return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
    1345         }
    1346         return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
    1347     }
    1348 
    1349     // convert an array to a date.
    1350     // the array should mirror the parameters below
    1351     // note: all values past the year are optional and will default to the lowest possible value.
    1352     // [year, month, day , hour, minute, second, millisecond]
    1353     function configFromArray (config) {
    1354         var i, date, input = [], currentDate, yearToUse;
    1355 
    1356         if (config._d) {
    1357             return;
    1358         }
    1359 
    1360         currentDate = currentDateArray(config);
    1361 
    1362         //compute day of the year from weeks and weekdays
    1363         if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
    1364             dayOfYearFromWeekInfo(config);
    1365         }
    1366 
    1367         //if the day of the year is set, figure out what it is
    1368         if (config._dayOfYear) {
    1369             yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
    1370 
    1371             if (config._dayOfYear > daysInYear(yearToUse)) {
    1372                 getParsingFlags(config)._overflowDayOfYear = true;
    1373             }
    1374 
    1375             date = createUTCDate(yearToUse, 0, config._dayOfYear);
    1376             config._a[MONTH] = date.getUTCMonth();
    1377             config._a[DATE] = date.getUTCDate();
    1378         }
    1379 
    1380         // Default to current date.
    1381         // * if no year, month, day of month are given, default to today
    1382         // * if day of month is given, default month and year
    1383         // * if month is given, default only year
    1384         // * if year is given, don't default anything
    1385         for (i = 0; i < 3 && config._a[i] == null; ++i) {
    1386             config._a[i] = input[i] = currentDate[i];
    1387         }
    1388 
    1389         // Zero out whatever was not defaulted, including time
    1390         for (; i < 7; i++) {
    1391             config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
    1392         }
    1393 
    1394         // Check for 24:00:00.000
    1395         if (config._a[HOUR] === 24 &&
    1396                 config._a[MINUTE] === 0 &&
    1397                 config._a[SECOND] === 0 &&
    1398                 config._a[MILLISECOND] === 0) {
    1399             config._nextDay = true;
    1400             config._a[HOUR] = 0;
    1401         }
    1402 
    1403         config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
    1404         // Apply timezone offset from input. The actual utcOffset can be changed
    1405         // with parseZone.
    1406         if (config._tzm != null) {
    1407             config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
    1408         }
    1409 
    1410         if (config._nextDay) {
    1411             config._a[HOUR] = 24;
    1412         }
    1413     }
    1414 
    1415     function dayOfYearFromWeekInfo(config) {
    1416         var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
    1417 
    1418         w = config._w;
    1419         if (w.GG != null || w.W != null || w.E != null) {
    1420             dow = 1;
    1421             doy = 4;
    1422 
    1423             // TODO: We need to take the current isoWeekYear, but that depends on
    1424             // how we interpret now (local, utc, fixed offset). So create
    1425             // a now version of current config (take local/utc/offset flags, and
    1426             // create now).
    1427             weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
    1428             week = defaults(w.W, 1);
    1429             weekday = defaults(w.E, 1);
    1430             if (weekday < 1 || weekday > 7) {
    1431                 weekdayOverflow = true;
    1432             }
    1433         } else {
    1434             dow = config._locale._week.dow;
    1435             doy = config._locale._week.doy;
    1436 
    1437             weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
    1438             week = defaults(w.w, 1);
    1439 
    1440             if (w.d != null) {
    1441                 // weekday -- low day numbers are considered next week
    1442                 weekday = w.d;
    1443                 if (weekday < 0 || weekday > 6) {
    1444                     weekdayOverflow = true;
    1445                 }
    1446             } else if (w.e != null) {
    1447                 // local weekday -- counting starts from begining of week
    1448                 weekday = w.e + dow;
    1449                 if (w.e < 0 || w.e > 6) {
    1450                     weekdayOverflow = true;
    1451                 }
    1452             } else {
    1453                 // default to begining of week
    1454                 weekday = dow;
    1455             }
    1456         }
    1457         if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
    1458             getParsingFlags(config)._overflowWeeks = true;
    1459         } else if (weekdayOverflow != null) {
    1460             getParsingFlags(config)._overflowWeekday = true;
    1461         } else {
    1462             temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
    1463             config._a[YEAR] = temp.year;
    1464             config._dayOfYear = temp.dayOfYear;
    1465         }
    1466     }
    1467 
    1468     // constant that refers to the ISO standard
    1469     utils_hooks__hooks.ISO_8601 = function () {};
    1470 
    1471     // date from string and format string
    1472     function configFromStringAndFormat(config) {
    1473         // TODO: Move this to another part of the creation flow to prevent circular deps
    1474         if (config._f === utils_hooks__hooks.ISO_8601) {
    1475             configFromISO(config);
    1476             return;
    1477         }
    1478 
    1479         config._a = [];
    1480         getParsingFlags(config).empty = true;
    1481 
    1482         // This array is used to make a Date, either with `new Date` or `Date.UTC`
    1483         var string = '' + config._i,
    1484             i, parsedInput, tokens, token, skipped,
    1485             stringLength = string.length,
    1486             totalParsedInputLength = 0;
    1487 
    1488         tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
    1489 
    1490         for (i = 0; i < tokens.length; i++) {
    1491             token = tokens[i];
    1492             parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
    1493             // console.log('token', token, 'parsedInput', parsedInput,
    1494             //         'regex', getParseRegexForToken(token, config));
    1495             if (parsedInput) {
    1496                 skipped = string.substr(0, string.indexOf(parsedInput));
    1497                 if (skipped.length > 0) {
    1498                     getParsingFlags(config).unusedInput.push(skipped);
    1499                 }
    1500                 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
    1501                 totalParsedInputLength += parsedInput.length;
    1502             }
    1503             // don't parse if it's not a known token
    1504             if (formatTokenFunctions[token]) {
    1505                 if (parsedInput) {
    1506                     getParsingFlags(config).empty = false;
    1507                 }
    1508                 else {
    1509                     getParsingFlags(config).unusedTokens.push(token);
    1510                 }
    1511                 addTimeToArrayFromToken(token, parsedInput, config);
    1512             }
    1513             else if (config._strict && !parsedInput) {
    1514                 getParsingFlags(config).unusedTokens.push(token);
    1515             }
    1516         }
    1517 
    1518         // add remaining unparsed input length to the string
    1519         getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
    1520         if (string.length > 0) {
    1521             getParsingFlags(config).unusedInput.push(string);
    1522         }
    1523 
    1524         // clear _12h flag if hour is <= 12
    1525         if (getParsingFlags(config).bigHour === true &&
    1526                 config._a[HOUR] <= 12 &&
    1527                 config._a[HOUR] > 0) {
    1528             getParsingFlags(config).bigHour = undefined;
    1529         }
    1530 
    1531         getParsingFlags(config).parsedDateParts = config._a.slice(0);
    1532         getParsingFlags(config).meridiem = config._meridiem;
    1533         // handle meridiem
    1534         config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
    1535 
    1536         configFromArray(config);
    1537         checkOverflow(config);
    1538     }
    1539 
    1540 
    1541     function meridiemFixWrap (locale, hour, meridiem) {
    1542         var isPm;
    1543 
    1544         if (meridiem == null) {
    1545             // nothing to do
    1546             return hour;
    1547         }
    1548         if (locale.meridiemHour != null) {
    1549             return locale.meridiemHour(hour, meridiem);
    1550         } else if (locale.isPM != null) {
    1551             // Fallback
    1552             isPm = locale.isPM(meridiem);
    1553             if (isPm && hour < 12) {
    1554                 hour += 12;
    1555             }
    1556             if (!isPm && hour === 12) {
    1557                 hour = 0;
    1558             }
    1559             return hour;
    1560         } else {
    1561             // this is not supposed to happen
    1562             return hour;
    1563         }
    1564     }
    1565 
    1566     // date from string and array of format strings
    1567     function configFromStringAndArray(config) {
    1568         var tempConfig,
    1569             bestMoment,
    1570 
    1571             scoreToBeat,
    1572             i,
    1573             currentScore;
    1574 
    1575         if (config._f.length === 0) {
    1576             getParsingFlags(config).invalidFormat = true;
    1577             config._d = new Date(NaN);
    1578             return;
    1579         }
    1580 
    1581         for (i = 0; i < config._f.length; i++) {
    1582             currentScore = 0;
    1583             tempConfig = copyConfig({}, config);
    1584             if (config._useUTC != null) {
    1585                 tempConfig._useUTC = config._useUTC;
    1586             }
    1587             tempConfig._f = config._f[i];
    1588             configFromStringAndFormat(tempConfig);
    1589 
    1590             if (!valid__isValid(tempConfig)) {
    1591                 continue;
    1592             }
    1593 
    1594             // if there is any input that was not parsed add a penalty for that format
    1595             currentScore += getParsingFlags(tempConfig).charsLeftOver;
    1596 
    1597             //or tokens
    1598             currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
    1599 
    1600             getParsingFlags(tempConfig).score = currentScore;
    1601 
    1602             if (scoreToBeat == null || currentScore < scoreToBeat) {
    1603                 scoreToBeat = currentScore;
    1604                 bestMoment = tempConfig;
    1605             }
    1606         }
    1607 
    1608         extend(config, bestMoment || tempConfig);
    1609     }
    1610 
    1611     function configFromObject(config) {
    1612         if (config._d) {
    1613             return;
    1614         }
    1615 
    1616         var i = normalizeObjectUnits(config._i);
    1617         config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
    1618             return obj && parseInt(obj, 10);
    1619         });
    1620 
    1621         configFromArray(config);
    1622     }
    1623 
    1624     function createFromConfig (config) {
    1625         var res = new Moment(checkOverflow(prepareConfig(config)));
    1626         if (res._nextDay) {
    1627             // Adding is smart enough around DST
    1628             res.add(1, 'd');
    1629             res._nextDay = undefined;
    1630         }
    1631 
    1632         return res;
    1633     }
    1634 
    1635     function prepareConfig (config) {
    1636         var input = config._i,
    1637             format = config._f;
    1638 
    1639         config._locale = config._locale || locale_locales__getLocale(config._l);
    1640 
    1641         if (input === null || (format === undefined && input === '')) {
    1642             return valid__createInvalid({nullInput: true});
    1643         }
    1644 
    1645         if (typeof input === 'string') {
    1646             config._i = input = config._locale.preparse(input);
    1647         }
    1648 
    1649         if (isMoment(input)) {
    1650             return new Moment(checkOverflow(input));
    1651         } else if (isArray(format)) {
    1652             configFromStringAndArray(config);
    1653         } else if (format) {
    1654             configFromStringAndFormat(config);
    1655         } else if (isDate(input)) {
    1656             config._d = input;
    1657         } else {
    1658             configFromInput(config);
    1659         }
    1660 
    1661         if (!valid__isValid(config)) {
    1662             config._d = null;
    1663         }
    1664 
    1665         return config;
    1666     }
    1667 
    1668     function configFromInput(config) {
    1669         var input = config._i;
    1670         if (input === undefined) {
    1671             config._d = new Date(utils_hooks__hooks.now());
    1672         } else if (isDate(input)) {
    1673             config._d = new Date(input.valueOf());
    1674         } else if (typeof input === 'string') {
    1675             configFromString(config);
    1676         } else if (isArray(input)) {
    1677             config._a = map(input.slice(0), function (obj) {
    1678                 return parseInt(obj, 10);
    1679             });
    1680             configFromArray(config);
    1681         } else if (typeof(input) === 'object') {
    1682             configFromObject(config);
    1683         } else if (typeof(input) === 'number') {
    1684             // from milliseconds
    1685             config._d = new Date(input);
    1686         } else {
    1687             utils_hooks__hooks.createFromInputFallback(config);
    1688         }
    1689     }
    1690 
    1691     function createLocalOrUTC (input, format, locale, strict, isUTC) {
    1692         var c = {};
    1693 
    1694         if (typeof(locale) === 'boolean') {
    1695             strict = locale;
    1696             locale = undefined;
    1697         }
    1698         // object construction must be done this way.
    1699         // https://github.com/moment/moment/issues/1423
    1700         c._isAMomentObject = true;
    1701         c._useUTC = c._isUTC = isUTC;
    1702         c._l = locale;
    1703         c._i = input;
    1704         c._f = format;
    1705         c._strict = strict;
    1706 
    1707         return createFromConfig(c);
    1708     }
    1709 
    1710     function local__createLocal (input, format, locale, strict) {
    1711         return createLocalOrUTC(input, format, locale, strict, false);
    1712     }
    1713 
    1714     var prototypeMin = deprecate(
    1715          'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
    1716          function () {
    1717              var other = local__createLocal.apply(null, arguments);
    1718              if (this.isValid() && other.isValid()) {
    1719                  return other < this ? this : other;
    1720              } else {
    1721                  return valid__createInvalid();
    1722              }
    1723          }
    1724      );
    1725 
    1726     var prototypeMax = deprecate(
    1727         'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
    1728         function () {
    1729             var other = local__createLocal.apply(null, arguments);
    1730             if (this.isValid() && other.isValid()) {
    1731                 return other > this ? this : other;
    1732             } else {
    1733                 return valid__createInvalid();
    1734             }
    1735         }
    1736     );
    1737 
    1738     // Pick a moment m from moments so that m[fn](other) is true for all
    1739     // other. This relies on the function fn to be transitive.
    1740     //
    1741     // moments should either be an array of moment objects or an array, whose
    1742     // first element is an array of moment objects.
    1743     function pickBy(fn, moments) {
    1744         var res, i;
    1745         if (moments.length === 1 && isArray(moments[0])) {
    1746             moments = moments[0];
    1747         }
    1748         if (!moments.length) {
    1749             return local__createLocal();
    1750         }
    1751         res = moments[0];
    1752         for (i = 1; i < moments.length; ++i) {
    1753             if (!moments[i].isValid() || moments[i][fn](res)) {
    1754                 res = moments[i];
    1755             }
    1756         }
    1757         return res;
    1758     }
    1759 
    1760     // TODO: Use [].sort instead?
    1761     function min () {
    1762         var args = [].slice.call(arguments, 0);
    1763 
    1764         return pickBy('isBefore', args);
    1765     }
    1766 
    1767     function max () {
    1768         var args = [].slice.call(arguments, 0);
    1769 
    1770         return pickBy('isAfter', args);
    1771     }
    1772 
    1773     var now = function () {
    1774         return Date.now ? Date.now() : +(new Date());
    1775     };
    1776 
    1777     function Duration (duration) {
    1778         var normalizedInput = normalizeObjectUnits(duration),
    1779             years = normalizedInput.year || 0,
    1780             quarters = normalizedInput.quarter || 0,
    1781             months = normalizedInput.month || 0,
    1782             weeks = normalizedInput.week || 0,
    1783             days = normalizedInput.day || 0,
    1784             hours = normalizedInput.hour || 0,
    1785             minutes = normalizedInput.minute || 0,
    1786             seconds = normalizedInput.second || 0,
    1787             milliseconds = normalizedInput.millisecond || 0;
    1788 
    1789         // representation for dateAddRemove
    1790         this._milliseconds = +milliseconds +
    1791             seconds * 1e3 + // 1000
    1792             minutes * 6e4 + // 1000 * 60
    1793             hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
    1794         // Because of dateAddRemove treats 24 hours as different from a
    1795         // day when working around DST, we need to store them separately
    1796         this._days = +days +
    1797             weeks * 7;
    1798         // It is impossible translate months into days without knowing
    1799         // which months you are are talking about, so we have to store
    1800         // it separately.
    1801         this._months = +months +
    1802             quarters * 3 +
    1803             years * 12;
    1804 
    1805         this._data = {};
    1806 
    1807         this._locale = locale_locales__getLocale();
    1808 
    1809         this._bubble();
    1810     }
    1811 
    1812     function isDuration (obj) {
    1813         return obj instanceof Duration;
    1814     }
    1815 
    1816     // FORMATTING
    1817 
    1818     function offset (token, separator) {
    1819         addFormatToken(token, 0, 0, function () {
    1820             var offset = this.utcOffset();
    1821             var sign = '+';
    1822             if (offset < 0) {
    1823                 offset = -offset;
    1824                 sign = '-';
    1825             }
    1826             return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
    1827         });
    1828     }
    1829 
    1830     offset('Z', ':');
    1831     offset('ZZ', '');
    1832 
    1833     // PARSING
    1834 
    1835     addRegexToken('Z',  matchShortOffset);
    1836     addRegexToken('ZZ', matchShortOffset);
    1837     addParseToken(['Z', 'ZZ'], function (input, array, config) {
    1838         config._useUTC = true;
    1839         config._tzm = offsetFromString(matchShortOffset, input);
    1840     });
    1841 
    1842     // HELPERS
    1843 
    1844     // timezone chunker
    1845     // '+10:00' > ['10',  '00']
    1846     // '-1530'  > ['-15', '30']
    1847     var chunkOffset = /([\+\-]|\d\d)/gi;
    1848 
    1849     function offsetFromString(matcher, string) {
    1850         var matches = ((string || '').match(matcher) || []);
    1851         var chunk   = matches[matches.length - 1] || [];
    1852         var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
    1853         var minutes = +(parts[1] * 60) + toInt(parts[2]);
    1854 
    1855         return parts[0] === '+' ? minutes : -minutes;
    1856     }
    1857 
    1858     // Return a moment from input, that is local/utc/zone equivalent to model.
    1859     function cloneWithOffset(input, model) {
    1860         var res, diff;
    1861         if (model._isUTC) {
    1862             res = model.clone();
    1863             diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
    1864             // Use low-level api, because this fn is low-level api.
    1865             res._d.setTime(res._d.valueOf() + diff);
    1866             utils_hooks__hooks.updateOffset(res, false);
    1867             return res;
    1868         } else {
    1869             return local__createLocal(input).local();
    1870         }
    1871     }
    1872 
    1873     function getDateOffset (m) {
    1874         // On Firefox.24 Date#getTimezoneOffset returns a floating point.
    1875         // https://github.com/moment/moment/pull/1871
    1876         return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
    1877     }
    1878 
    1879     // HOOKS
    1880 
    1881     // This function will be called whenever a moment is mutated.
    1882     // It is intended to keep the offset in sync with the timezone.
    1883     utils_hooks__hooks.updateOffset = function () {};
    1884 
    1885     // MOMENTS
    1886 
    1887     // keepLocalTime = true means only change the timezone, without
    1888     // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
    1889     // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
    1890     // +0200, so we adjust the time as needed, to be valid.
    1891     //
    1892     // Keeping the time actually adds/subtracts (one hour)
    1893     // from the actual represented time. That is why we call updateOffset
    1894     // a second time. In case it wants us to change the offset again
    1895     // _changeInProgress == true case, then we have to adjust, because
    1896     // there is no such time in the given timezone.
    1897     function getSetOffset (input, keepLocalTime) {
    1898         var offset = this._offset || 0,
    1899             localAdjust;
    1900         if (!this.isValid()) {
    1901             return input != null ? this : NaN;
    1902         }
    1903         if (input != null) {
    1904             if (typeof input === 'string') {
    1905                 input = offsetFromString(matchShortOffset, input);
    1906             } else if (Math.abs(input) < 16) {
    1907                 input = input * 60;
    1908             }
    1909             if (!this._isUTC && keepLocalTime) {
    1910                 localAdjust = getDateOffset(this);
    1911             }
    1912             this._offset = input;
    1913             this._isUTC = true;
    1914             if (localAdjust != null) {
    1915                 this.add(localAdjust, 'm');
    1916             }
    1917             if (offset !== input) {
    1918                 if (!keepLocalTime || this._changeInProgress) {
    1919                     add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
    1920                 } else if (!this._changeInProgress) {
    1921                     this._changeInProgress = true;
    1922                     utils_hooks__hooks.updateOffset(this, true);
    1923                     this._changeInProgress = null;
    1924                 }
    1925             }
    1926             return this;
    1927         } else {
    1928             return this._isUTC ? offset : getDateOffset(this);
    1929         }
    1930     }
    1931 
    1932     function getSetZone (input, keepLocalTime) {
    1933         if (input != null) {
    1934             if (typeof input !== 'string') {
    1935                 input = -input;
    1936             }
    1937 
    1938             this.utcOffset(input, keepLocalTime);
    1939 
    1940             return this;
    1941         } else {
    1942             return -this.utcOffset();
    1943         }
    1944     }
    1945 
    1946     function setOffsetToUTC (keepLocalTime) {
    1947         return this.utcOffset(0, keepLocalTime);
    1948     }
    1949 
    1950     function setOffsetToLocal (keepLocalTime) {
    1951         if (this._isUTC) {
    1952             this.utcOffset(0, keepLocalTime);
    1953             this._isUTC = false;
    1954 
    1955             if (keepLocalTime) {
    1956                 this.subtract(getDateOffset(this), 'm');
    1957             }
    1958         }
    1959         return this;
    1960     }
    1961 
    1962     function setOffsetToParsedOffset () {
    1963         if (this._tzm) {
    1964             this.utcOffset(this._tzm);
    1965         } else if (typeof this._i === 'string') {
    1966             this.utcOffset(offsetFromString(matchOffset, this._i));
    1967         }
    1968         return this;
    1969     }
    1970 
    1971     function hasAlignedHourOffset (input) {
    1972         if (!this.isValid()) {
    1973             return false;
    1974         }
    1975         input = input ? local__createLocal(input).utcOffset() : 0;
    1976 
    1977         return (this.utcOffset() - input) % 60 === 0;
    1978     }
    1979 
    1980     function isDaylightSavingTime () {
    1981         return (
    1982             this.utcOffset() > this.clone().month(0).utcOffset() ||
    1983             this.utcOffset() > this.clone().month(5).utcOffset()
    1984         );
    1985     }
    1986 
    1987     function isDaylightSavingTimeShifted () {
    1988         if (!isUndefined(this._isDSTShifted)) {
    1989             return this._isDSTShifted;
    1990         }
    1991 
    1992         var c = {};
    1993 
    1994         copyConfig(c, this);
    1995         c = prepareConfig(c);
    1996 
    1997         if (c._a) {
    1998             var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
    1999             this._isDSTShifted = this.isValid() &&
    2000                 compareArrays(c._a, other.toArray()) > 0;
    2001         } else {
    2002             this._isDSTShifted = false;
    2003         }
    2004 
    2005         return this._isDSTShifted;
    2006     }
    2007 
    2008     function isLocal () {
    2009         return this.isValid() ? !this._isUTC : false;
    2010     }
    2011 
    2012     function isUtcOffset () {
    2013         return this.isValid() ? this._isUTC : false;
    2014     }
    2015 
    2016     function isUtc () {
    2017         return this.isValid() ? this._isUTC && this._offset === 0 : false;
    2018     }
    2019 
    2020     // ASP.NET json date format regex
    2021     var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
    2022 
    2023     // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
    2024     // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
    2025     // and further modified to allow for strings containing both week and day
    2026     var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
    2027 
    2028     function create__createDuration (input, key) {
    2029         var duration = input,
    2030             // matching against regexp is expensive, do it on demand
    2031             match = null,
    2032             sign,
    2033             ret,
    2034             diffRes;
    2035 
    2036         if (isDuration(input)) {
    2037             duration = {
    2038                 ms : input._milliseconds,
    2039                 d  : input._days,
    2040                 M  : input._months
    2041             };
    2042         } else if (typeof input === 'number') {
    2043             duration = {};
    2044             if (key) {
    2045                 duration[key] = input;
    2046             } else {
    2047                 duration.milliseconds = input;
    2048             }
    2049         } else if (!!(match = aspNetRegex.exec(input))) {
    2050             sign = (match[1] === '-') ? -1 : 1;
    2051             duration = {
    2052                 y  : 0,
    2053                 d  : toInt(match[DATE])        * sign,
    2054                 h  : toInt(match[HOUR])        * sign,
    2055                 m  : toInt(match[MINUTE])      * sign,
    2056                 s  : toInt(match[SECOND])      * sign,
    2057                 ms : toInt(match[MILLISECOND]) * sign
    2058             };
    2059         } else if (!!(match = isoRegex.exec(input))) {
    2060             sign = (match[1] === '-') ? -1 : 1;
    2061             duration = {
    2062                 y : parseIso(match[2], sign),
    2063                 M : parseIso(match[3], sign),
    2064                 w : parseIso(match[4], sign),
    2065                 d : parseIso(match[5], sign),
    2066                 h : parseIso(match[6], sign),
    2067                 m : parseIso(match[7], sign),
    2068                 s : parseIso(match[8], sign)
    2069             };
    2070         } else if (duration == null) {// checks for null or undefined
    2071             duration = {};
    2072         } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
    2073             diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
    2074 
    2075             duration = {};
    2076             duration.ms = diffRes.milliseconds;
    2077             duration.M = diffRes.months;
    2078         }
    2079 
    2080         ret = new Duration(duration);
    2081 
    2082         if (isDuration(input) && hasOwnProp(input, '_locale')) {
    2083             ret._locale = input._locale;
    2084         }
    2085 
    2086         return ret;
    2087     }
    2088 
    2089     create__createDuration.fn = Duration.prototype;
    2090 
    2091     function parseIso (inp, sign) {
    2092         // We'd normally use ~~inp for this, but unfortunately it also
    2093         // converts floats to ints.
    2094         // inp may be undefined, so careful calling replace on it.
    2095         var res = inp && parseFloat(inp.replace(',', '.'));
    2096         // apply sign while we're at it
    2097         return (isNaN(res) ? 0 : res) * sign;
    2098     }
    2099 
    2100     function positiveMomentsDifference(base, other) {
    2101         var res = {milliseconds: 0, months: 0};
    2102 
    2103         res.months = other.month() - base.month() +
    2104             (other.year() - base.year()) * 12;
    2105         if (base.clone().add(res.months, 'M').isAfter(other)) {
    2106             --res.months;
    2107         }
    2108 
    2109         res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
    2110 
    2111         return res;
    2112     }
    2113 
    2114     function momentsDifference(base, other) {
    2115         var res;
    2116         if (!(base.isValid() && other.isValid())) {
    2117             return {milliseconds: 0, months: 0};
    2118         }
    2119 
    2120         other = cloneWithOffset(other, base);
    2121         if (base.isBefore(other)) {
    2122             res = positiveMomentsDifference(base, other);
    2123         } else {
    2124             res = positiveMomentsDifference(other, base);
    2125             res.milliseconds = -res.milliseconds;
    2126             res.months = -res.months;
    2127         }
    2128 
    2129         return res;
    2130     }
    2131 
    2132     function absRound (number) {
    2133         if (number < 0) {
    2134             return Math.round(-1 * number) * -1;
    2135         } else {
    2136             return Math.round(number);
    2137         }
    2138     }
    2139 
    2140     // TODO: remove 'name' arg after deprecation is removed
    2141     function createAdder(direction, name) {
    2142         return function (val, period) {
    2143             var dur, tmp;
    2144             //invert the arguments, but complain about it
    2145             if (period !== null && !isNaN(+period)) {
    2146                 deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
    2147                 tmp = val; val = period; period = tmp;
    2148             }
    2149 
    2150             val = typeof val === 'string' ? +val : val;
    2151             dur = create__createDuration(val, period);
    2152             add_subtract__addSubtract(this, dur, direction);
    2153             return this;
    2154         };
    2155     }
    2156 
    2157     function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
    2158         var milliseconds = duration._milliseconds,
    2159             days = absRound(duration._days),
    2160             months = absRound(duration._months);
    2161 
    2162         if (!mom.isValid()) {
    2163             // No op
    2164             return;
    2165         }
    2166 
    2167         updateOffset = updateOffset == null ? true : updateOffset;
    2168 
    2169         if (milliseconds) {
    2170             mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
    2171         }
    2172         if (days) {
    2173             get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
    2174         }
    2175         if (months) {
    2176             setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
    2177         }
    2178         if (updateOffset) {
    2179             utils_hooks__hooks.updateOffset(mom, days || months);
    2180         }
    2181     }
    2182 
    2183     var add_subtract__add      = createAdder(1, 'add');
    2184     var add_subtract__subtract = createAdder(-1, 'subtract');
    2185 
    2186     function moment_calendar__calendar (time, formats) {
    2187         // We want to compare the start of today, vs this.
    2188         // Getting start-of-today depends on whether we're local/utc/offset or not.
    2189         var now = time || local__createLocal(),
    2190             sod = cloneWithOffset(now, this).startOf('day'),
    2191             diff = this.diff(sod, 'days', true),
    2192             format = diff < -6 ? 'sameElse' :
    2193                 diff < -1 ? 'lastWeek' :
    2194                 diff < 0 ? 'lastDay' :
    2195                 diff < 1 ? 'sameDay' :
    2196                 diff < 2 ? 'nextDay' :
    2197                 diff < 7 ? 'nextWeek' : 'sameElse';
    2198 
    2199         var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
    2200 
    2201         return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
    2202     }
    2203 
    2204     function clone () {
    2205         return new Moment(this);
    2206     }
    2207 
    2208     function isAfter (input, units) {
    2209         var localInput = isMoment(input) ? input : local__createLocal(input);
    2210         if (!(this.isValid() && localInput.isValid())) {
    2211             return false;
    2212         }
    2213         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
    2214         if (units === 'millisecond') {
    2215             return this.valueOf() > localInput.valueOf();
    2216         } else {
    2217             return localInput.valueOf() < this.clone().startOf(units).valueOf();
    2218         }
    2219     }
    2220 
    2221     function isBefore (input, units) {
    2222         var localInput = isMoment(input) ? input : local__createLocal(input);
    2223         if (!(this.isValid() && localInput.isValid())) {
    2224             return false;
    2225         }
    2226         units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
    2227         if (units === 'millisecond') {
    2228             return this.valueOf() < localInput.valueOf();
    2229         } else {
    2230             return this.clone().endOf(units).valueOf() < localInput.valueOf();
    2231         }
    2232     }
    2233 
    2234     function isBetween (from, to, units, inclusivity) {
    2235         inclusivity = inclusivity || '()';
    2236         return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
    2237             (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
    2238     }
    2239 
    2240     function isSame (input, units) {
    2241         var localInput = isMoment(input) ? input : local__createLocal(input),
    2242             inputMs;
    2243         if (!(this.isValid() && localInput.isValid())) {
    2244             return false;
    2245         }
    2246         units = normalizeUnits(units || 'millisecond');
    2247         if (units === 'millisecond') {
    2248             return this.valueOf() === localInput.valueOf();
    2249         } else {
    2250             inputMs = localInput.valueOf();
    2251             return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
    2252         }
    2253     }
    2254 
    2255     function isSameOrAfter (input, units) {
    2256         return this.isSame(input, units) || this.isAfter(input,units);
    2257     }
    2258 
    2259     function isSameOrBefore (input, units) {
    2260         return this.isSame(input, units) || this.isBefore(input,units);
    2261     }
    2262 
    2263     function diff (input, units, asFloat) {
    2264         var that,
    2265             zoneDelta,
    2266             delta, output;
    2267 
    2268         if (!this.isValid()) {
    2269             return NaN;
    2270         }
    2271 
    2272         that = cloneWithOffset(input, this);
    2273 
    2274         if (!that.isValid()) {
    2275             return NaN;
    2276         }
    2277 
    2278         zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
    2279 
    2280         units = normalizeUnits(units);
    2281 
    2282         if (units === 'year' || units === 'month' || units === 'quarter') {
    2283             output = monthDiff(this, that);
    2284             if (units === 'quarter') {
    2285                 output = output / 3;
    2286             } else if (units === 'year') {
    2287                 output = output / 12;
    2288             }
    2289         } else {
    2290             delta = this - that;
    2291             output = units === 'second' ? delta / 1e3 : // 1000
    2292                 units === 'minute' ? delta / 6e4 : // 1000 * 60
    2293                 units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
    2294                 units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
    2295                 units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
    2296                 delta;
    2297         }
    2298         return asFloat ? output : absFloor(output);
    2299     }
    2300 
    2301     function monthDiff (a, b) {
    2302         // difference in months
    2303         var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
    2304             // b is in (anchor - 1 month, anchor + 1 month)
    2305             anchor = a.clone().add(wholeMonthDiff, 'months'),
    2306             anchor2, adjust;
    2307 
    2308         if (b - anchor < 0) {
    2309             anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
    2310             // linear across the month
    2311             adjust = (b - anchor) / (anchor - anchor2);
    2312         } else {
    2313             anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
    2314             // linear across the month
    2315             adjust = (b - anchor) / (anchor2 - anchor);
    2316         }
    2317 
    2318         //check for negative zero, return zero if negative zero
    2319         return -(wholeMonthDiff + adjust) || 0;
    2320     }
    2321 
    2322     utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
    2323     utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
    2324 
    2325     function toString () {
    2326         return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
    2327     }
    2328 
    2329     function moment_format__toISOString () {
    2330         var m = this.clone().utc();
    2331         if (0 < m.year() && m.year() <= 9999) {
    2332             if (isFunction(Date.prototype.toISOString)) {
    2333                 // native implementation is ~50x faster, use it when we can
    2334                 return this.toDate().toISOString();
    2335             } else {
    2336                 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
    2337             }
    2338         } else {
    2339             return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
    2340         }
    2341     }
    2342 
    2343     function format (inputString) {
    2344         if (!inputString) {
    2345             inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
    2346         }
    2347         var output = formatMoment(this, inputString);
    2348         return this.localeData().postformat(output);
    2349     }
    2350 
    2351     function from (time, withoutSuffix) {
    2352         if (this.isValid() &&
    2353                 ((isMoment(time) && time.isValid()) ||
    2354                  local__createLocal(time).isValid())) {
    2355             return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
    2356         } else {
    2357             return this.localeData().invalidDate();
    2358         }
    2359     }
    2360 
    2361     function fromNow (withoutSuffix) {
    2362         return this.from(local__createLocal(), withoutSuffix);
    2363     }
    2364 
    2365     function to (time, withoutSuffix) {
    2366         if (this.isValid() &&
    2367                 ((isMoment(time) && time.isValid()) ||
    2368                  local__createLocal(time).isValid())) {
    2369             return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
    2370         } else {
    2371             return this.localeData().invalidDate();
    2372         }
    2373     }
    2374 
    2375     function toNow (withoutSuffix) {
    2376         return this.to(local__createLocal(), withoutSuffix);
    2377     }
    2378 
    2379     // If passed a locale key, it will set the locale for this
    2380     // instance.  Otherwise, it will return the locale configuration
    2381     // variables for this instance.
    2382     function locale (key) {
    2383         var newLocaleData;
    2384 
    2385         if (key === undefined) {
    2386             return this._locale._abbr;
    2387         } else {
    2388             newLocaleData = locale_locales__getLocale(key);
    2389             if (newLocaleData != null) {
    2390                 this._locale = newLocaleData;
    2391             }
    2392             return this;
    2393         }
    2394     }
    2395 
    2396     var lang = deprecate(
    2397         'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
    2398         function (key) {
    2399             if (key === undefined) {
    2400                 return this.localeData();
    2401             } else {
    2402                 return this.locale(key);
    2403             }
    2404         }
    2405     );
    2406 
    2407     function localeData () {
    2408         return this._locale;
    2409     }
    2410 
    2411     function startOf (units) {
    2412         units = normalizeUnits(units);
    2413         // the following switch intentionally omits break keywords
    2414         // to utilize falling through the cases.
    2415         switch (units) {
    2416         case 'year':
    2417             this.month(0);
    2418             /* falls through */
    2419         case 'quarter':
    2420         case 'month':
    2421             this.date(1);
    2422             /* falls through */
    2423         case 'week':
    2424         case 'isoWeek':
    2425         case 'day':
    2426         case 'date':
    2427             this.hours(0);
    2428             /* falls through */
    2429         case 'hour':
    2430             this.minutes(0);
    2431             /* falls through */
    2432         case 'minute':
    2433             this.seconds(0);
    2434             /* falls through */
    2435         case 'second':
    2436             this.milliseconds(0);
    2437         }
    2438 
    2439         // weeks are a special case
    2440         if (units === 'week') {
    2441             this.weekday(0);
    2442         }
    2443         if (units === 'isoWeek') {
    2444             this.isoWeekday(1);
    2445         }
    2446 
    2447         // quarters are also special
    2448         if (units === 'quarter') {
    2449             this.month(Math.floor(this.month() / 3) * 3);
    2450         }
    2451 
    2452         return this;
    2453     }
    2454 
    2455     function endOf (units) {
    2456         units = normalizeUnits(units);
    2457         if (units === undefined || units === 'millisecond') {
    2458             return this;
    2459         }
    2460 
    2461         // 'date' is an alias for 'day', so it should be considered as such.
    2462         if (units === 'date') {
    2463             units = 'day';
    2464         }
    2465 
    2466         return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
    2467     }
    2468 
    2469     function to_type__valueOf () {
    2470         return this._d.valueOf() - ((this._offset || 0) * 60000);
    2471     }
    2472 
    2473     function unix () {
    2474         return Math.floor(this.valueOf() / 1000);
    2475     }
    2476 
    2477     function toDate () {
    2478         return this._offset ? new Date(this.valueOf()) : this._d;
    2479     }
    2480 
    2481     function toArray () {
    2482         var m = this;
    2483         return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
    2484     }
    2485 
    2486     function toObject () {
    2487         var m = this;
    2488         return {
    2489             years: m.year(),
    2490             months: m.month(),
    2491             date: m.date(),
    2492             hours: m.hours(),
    2493             minutes: m.minutes(),
    2494             seconds: m.seconds(),
    2495             milliseconds: m.milliseconds()
    2496         };
    2497     }
    2498 
    2499     function toJSON () {
    2500         // new Date(NaN).toJSON() === null
    2501         return this.isValid() ? this.toISOString() : null;
    2502     }
    2503 
    2504     function moment_valid__isValid () {
    2505         return valid__isValid(this);
    2506     }
    2507 
    2508     function parsingFlags () {
    2509         return extend({}, getParsingFlags(this));
    2510     }
    2511 
    2512     function invalidAt () {
    2513         return getParsingFlags(this).overflow;
    2514     }
    2515 
    2516     function creationData() {
    2517         return {
    2518             input: this._i,
    2519             format: this._f,
    2520             locale: this._locale,
    2521             isUTC: this._isUTC,
    2522             strict: this._strict
    2523         };
    2524     }
    2525 
    2526     // FORMATTING
    2527 
    2528     addFormatToken(0, ['gg', 2], 0, function () {
    2529         return this.weekYear() % 100;
    2530     });
    2531 
    2532     addFormatToken(0, ['GG', 2], 0, function () {
    2533         return this.isoWeekYear() % 100;
    2534     });
    2535 
    2536     function addWeekYearFormatToken (token, getter) {
    2537         addFormatToken(0, [token, token.length], 0, getter);
    2538     }
    2539 
    2540     addWeekYearFormatToken('gggg',     'weekYear');
    2541     addWeekYearFormatToken('ggggg',    'weekYear');
    2542     addWeekYearFormatToken('GGGG',  'isoWeekYear');
    2543     addWeekYearFormatToken('GGGGG', 'isoWeekYear');
    2544 
    2545     // ALIASES
    2546 
    2547     addUnitAlias('weekYear', 'gg');
    2548     addUnitAlias('isoWeekYear', 'GG');
    2549 
    2550     // PARSING
    2551 
    2552     addRegexToken('G',      matchSigned);
    2553     addRegexToken('g',      matchSigned);
    2554     addRegexToken('GG',     match1to2, match2);
    2555     addRegexToken('gg',     match1to2, match2);
    2556     addRegexToken('GGGG',   match1to4, match4);
    2557     addRegexToken('gggg',   match1to4, match4);
    2558     addRegexToken('GGGGG',  match1to6, match6);
    2559     addRegexToken('ggggg',  match1to6, match6);
    2560 
    2561     addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
    2562         week[token.substr(0, 2)] = toInt(input);
    2563     });
    2564 
    2565     addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
    2566         week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
    2567     });
    2568 
    2569     // MOMENTS
    2570 
    2571     function getSetWeekYear (input) {
    2572         return getSetWeekYearHelper.call(this,
    2573                 input,
    2574                 this.week(),
    2575                 this.weekday(),
    2576                 this.localeData()._week.dow,
    2577                 this.localeData()._week.doy);
    2578     }
    2579 
    2580     function getSetISOWeekYear (input) {
    2581         return getSetWeekYearHelper.call(this,
    2582                 input, this.isoWeek(), this.isoWeekday(), 1, 4);
    2583     }
    2584 
    2585     function getISOWeeksInYear () {
    2586         return weeksInYear(this.year(), 1, 4);
    2587     }
    2588 
    2589     function getWeeksInYear () {
    2590         var weekInfo = this.localeData()._week;
    2591         return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
    2592     }
    2593 
    2594     function getSetWeekYearHelper(input, week, weekday, dow, doy) {
    2595         var weeksTarget;
    2596         if (input == null) {
    2597             return weekOfYear(this, dow, doy).year;
    2598         } else {
    2599             weeksTarget = weeksInYear(input, dow, doy);
    2600             if (week > weeksTarget) {
    2601                 week = weeksTarget;
    2602             }
    2603             return setWeekAll.call(this, input, week, weekday, dow, doy);
    2604         }
    2605     }
    2606 
    2607     function setWeekAll(weekYear, week, weekday, dow, doy) {
    2608         var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
    2609             date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
    2610 
    2611         this.year(date.getUTCFullYear());
    2612         this.month(date.getUTCMonth());
    2613         this.date(date.getUTCDate());
    2614         return this;
    2615     }
    2616 
    2617     // FORMATTING
    2618 
    2619     addFormatToken('Q', 0, 'Qo', 'quarter');
    2620 
    2621     // ALIASES
    2622 
    2623     addUnitAlias('quarter', 'Q');
    2624 
    2625     // PARSING
    2626 
    2627     addRegexToken('Q', match1);
    2628     addParseToken('Q', function (input, array) {
    2629         array[MONTH] = (toInt(input) - 1) * 3;
    2630     });
    2631 
    2632     // MOMENTS
    2633 
    2634     function getSetQuarter (input) {
    2635         return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
    2636     }
    2637 
    26381196    // FORMATTING
    26391197
     
    26451203    addUnitAlias('week', 'w');
    26461204    addUnitAlias('isoWeek', 'W');
     1205
     1206    // PRIORITIES
     1207
     1208    addUnitPriority('week', 5);
     1209    addUnitPriority('isoWeek', 5);
    26471210
    26481211    // PARSING
     
    26921255    // FORMATTING
    26931256
    2694     addFormatToken('D', ['DD', 2], 'Do', 'date');
    2695 
    2696     // ALIASES
    2697 
    2698     addUnitAlias('date', 'D');
    2699 
    2700     // PARSING
    2701 
    2702     addRegexToken('D',  match1to2);
    2703     addRegexToken('DD', match1to2, match2);
    2704     addRegexToken('Do', function (isStrict, locale) {
    2705         return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
    2706     });
    2707 
    2708     addParseToken(['D', 'DD'], DATE);
    2709     addParseToken('Do', function (input, array) {
    2710         array[DATE] = toInt(input.match(match1to2)[0], 10);
    2711     });
    2712 
    2713     // MOMENTS
    2714 
    2715     var getSetDayOfMonth = makeGetSet('Date', true);
    2716 
    2717     // FORMATTING
    2718 
    27191257    addFormatToken('d', 0, 'do', 'day');
    27201258
     
    27391277    addUnitAlias('weekday', 'e');
    27401278    addUnitAlias('isoWeekday', 'E');
     1279
     1280    // PRIORITY
     1281    addUnitPriority('day', 11);
     1282    addUnitPriority('weekday', 11);
     1283    addUnitPriority('isoWeekday', 11);
    27411284
    27421285    // PARSING
     
    27881331    }
    27891332
     1333    function parseIsoWeekday(input, locale) {
     1334        if (typeof input === 'string') {
     1335            return locale.weekdaysParse(input) % 7 || 7;
     1336        }
     1337        return isNaN(input) ? null : input;
     1338    }
     1339
    27901340    // LOCALES
    27911341
    27921342    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
    27931343    function localeWeekdays (m, format) {
     1344        if (!m) {
     1345            return this._weekdays;
     1346        }
    27941347        return isArray(this._weekdays) ? this._weekdays[m.day()] :
    27951348            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
     
    27981351    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
    27991352    function localeWeekdaysShort (m) {
    2800         return this._weekdaysShort[m.day()];
     1353        return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
    28011354    }
    28021355
    28031356    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
    28041357    function localeWeekdaysMin (m) {
    2805         return this._weekdaysMin[m.day()];
     1358        return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
    28061359    }
    28071360
     
    29371490            return input != null ? this : NaN;
    29381491        }
     1492
    29391493        // behaves the same as moment#day except
    29401494        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
    29411495        // as a setter, sunday should belong to the previous week.
    2942         return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
     1496
     1497        if (input != null) {
     1498            var weekday = parseIsoWeekday(input, this.localeData());
     1499            return this.day(this.day() % 7 ? weekday : weekday - 7);
     1500        } else {
     1501            return this.day() || 7;
     1502        }
    29431503    }
    29441504
     
    29551515            }
    29561516        } else {
     1517            if (!hasOwnProp(this, '_weekdaysRegex')) {
     1518                this._weekdaysRegex = defaultWeekdaysRegex;
     1519            }
    29571520            return this._weekdaysStrictRegex && isStrict ?
    29581521                this._weekdaysStrictRegex : this._weekdaysRegex;
     
    29721535            }
    29731536        } else {
     1537            if (!hasOwnProp(this, '_weekdaysShortRegex')) {
     1538                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
     1539            }
    29741540            return this._weekdaysShortStrictRegex && isStrict ?
    29751541                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
     
    29891555            }
    29901556        } else {
     1557            if (!hasOwnProp(this, '_weekdaysMinRegex')) {
     1558                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
     1559            }
    29911560            return this._weekdaysMinStrictRegex && isStrict ?
    29921561                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
     
    30381607    // FORMATTING
    30391608
    3040     addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
    3041 
    3042     // ALIASES
    3043 
    3044     addUnitAlias('dayOfYear', 'DDD');
    3045 
    3046     // PARSING
    3047 
    3048     addRegexToken('DDD',  match1to3);
    3049     addRegexToken('DDDD', match3);
    3050     addParseToken(['DDD', 'DDDD'], function (input, array, config) {
    3051         config._dayOfYear = toInt(input);
    3052     });
    3053 
    3054     // HELPERS
    3055 
    3056     // MOMENTS
    3057 
    3058     function getSetDayOfYear (input) {
    3059         var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
    3060         return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
    3061     }
    3062 
    3063     // FORMATTING
    3064 
    30651609    function hFormat() {
    30661610        return this.hours() % 12 || 12;
     
    31051649
    31061650    addUnitAlias('hour', 'h');
     1651
     1652    // PRIORITY
     1653    addUnitPriority('hour', 13);
    31071654
    31081655    // PARSING
     
    31861733    var getSetHour = makeGetSet('Hours', true);
    31871734
     1735    var baseConfig = {
     1736        calendar: defaultCalendar,
     1737        longDateFormat: defaultLongDateFormat,
     1738        invalidDate: defaultInvalidDate,
     1739        ordinal: defaultOrdinal,
     1740        ordinalParse: defaultOrdinalParse,
     1741        relativeTime: defaultRelativeTime,
     1742
     1743        months: defaultLocaleMonths,
     1744        monthsShort: defaultLocaleMonthsShort,
     1745
     1746        week: defaultLocaleWeek,
     1747
     1748        weekdays: defaultLocaleWeekdays,
     1749        weekdaysMin: defaultLocaleWeekdaysMin,
     1750        weekdaysShort: defaultLocaleWeekdaysShort,
     1751
     1752        meridiemParse: defaultLocaleMeridiemParse
     1753    };
     1754
     1755    // internal storage for locale config files
     1756    var locales = {};
     1757    var globalLocale;
     1758
     1759    function normalizeLocale(key) {
     1760        return key ? key.toLowerCase().replace('_', '-') : key;
     1761    }
     1762
     1763    // pick the locale from the array
     1764    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
     1765    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
     1766    function chooseLocale(names) {
     1767        var i = 0, j, next, locale, split;
     1768
     1769        while (i < names.length) {
     1770            split = normalizeLocale(names[i]).split('-');
     1771            j = split.length;
     1772            next = normalizeLocale(names[i + 1]);
     1773            next = next ? next.split('-') : null;
     1774            while (j > 0) {
     1775                locale = loadLocale(split.slice(0, j).join('-'));
     1776                if (locale) {
     1777                    return locale;
     1778                }
     1779                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
     1780                    //the next array item is better than a shallower substring of this one
     1781                    break;
     1782                }
     1783                j--;
     1784            }
     1785            i++;
     1786        }
     1787        return null;
     1788    }
     1789
     1790    function loadLocale(name) {
     1791        var oldLocale = null;
     1792        // TODO: Find a better way to register and load all the locales in Node
     1793        if (!locales[name] && (typeof module !== 'undefined') &&
     1794                module && module.exports) {
     1795            try {
     1796                oldLocale = globalLocale._abbr;
     1797                require('./locale/' + name);
     1798                // because defineLocale currently also sets the global locale, we
     1799                // want to undo that for lazy loaded locales
     1800                locale_locales__getSetGlobalLocale(oldLocale);
     1801            } catch (e) { }
     1802        }
     1803        return locales[name];
     1804    }
     1805
     1806    // This function will load locale and then set the global locale.  If
     1807    // no arguments are passed in, it will simply return the current global
     1808    // locale key.
     1809    function locale_locales__getSetGlobalLocale (key, values) {
     1810        var data;
     1811        if (key) {
     1812            if (isUndefined(values)) {
     1813                data = locale_locales__getLocale(key);
     1814            }
     1815            else {
     1816                data = defineLocale(key, values);
     1817            }
     1818
     1819            if (data) {
     1820                // moment.duration._locale = moment._locale = data;
     1821                globalLocale = data;
     1822            }
     1823        }
     1824
     1825        return globalLocale._abbr;
     1826    }
     1827
     1828    function defineLocale (name, config) {
     1829        if (config !== null) {
     1830            var parentConfig = baseConfig;
     1831            config.abbr = name;
     1832            if (locales[name] != null) {
     1833                deprecateSimple('defineLocaleOverride',
     1834                        'use moment.updateLocale(localeName, config) to change ' +
     1835                        'an existing locale. moment.defineLocale(localeName, ' +
     1836                        'config) should only be used for creating a new locale ' +
     1837                        'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
     1838                parentConfig = locales[name]._config;
     1839            } else if (config.parentLocale != null) {
     1840                if (locales[config.parentLocale] != null) {
     1841                    parentConfig = locales[config.parentLocale]._config;
     1842                } else {
     1843                    // treat as if there is no base config
     1844                    deprecateSimple('parentLocaleUndefined',
     1845                            'specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/');
     1846                }
     1847            }
     1848            locales[name] = new Locale(mergeConfigs(parentConfig, config));
     1849
     1850            // backwards compat for now: also set the locale
     1851            locale_locales__getSetGlobalLocale(name);
     1852
     1853            return locales[name];
     1854        } else {
     1855            // useful for testing
     1856            delete locales[name];
     1857            return null;
     1858        }
     1859    }
     1860
     1861    function updateLocale(name, config) {
     1862        if (config != null) {
     1863            var locale, parentConfig = baseConfig;
     1864            // MERGE
     1865            if (locales[name] != null) {
     1866                parentConfig = locales[name]._config;
     1867            }
     1868            config = mergeConfigs(parentConfig, config);
     1869            locale = new Locale(config);
     1870            locale.parentLocale = locales[name];
     1871            locales[name] = locale;
     1872
     1873            // backwards compat for now: also set the locale
     1874            locale_locales__getSetGlobalLocale(name);
     1875        } else {
     1876            // pass null for config to unupdate, useful for tests
     1877            if (locales[name] != null) {
     1878                if (locales[name].parentLocale != null) {
     1879                    locales[name] = locales[name].parentLocale;
     1880                } else if (locales[name] != null) {
     1881                    delete locales[name];
     1882                }
     1883            }
     1884        }
     1885        return locales[name];
     1886    }
     1887
     1888    // returns locale data
     1889    function locale_locales__getLocale (key) {
     1890        var locale;
     1891
     1892        if (key && key._locale && key._locale._abbr) {
     1893            key = key._locale._abbr;
     1894        }
     1895
     1896        if (!key) {
     1897            return globalLocale;
     1898        }
     1899
     1900        if (!isArray(key)) {
     1901            //short-circuit everything else
     1902            locale = loadLocale(key);
     1903            if (locale) {
     1904                return locale;
     1905            }
     1906            key = [key];
     1907        }
     1908
     1909        return chooseLocale(key);
     1910    }
     1911
     1912    function locale_locales__listLocales() {
     1913        return keys(locales);
     1914    }
     1915
     1916    function checkOverflow (m) {
     1917        var overflow;
     1918        var a = m._a;
     1919
     1920        if (a && getParsingFlags(m).overflow === -2) {
     1921            overflow =
     1922                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
     1923                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
     1924                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
     1925                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
     1926                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
     1927                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
     1928                -1;
     1929
     1930            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
     1931                overflow = DATE;
     1932            }
     1933            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
     1934                overflow = WEEK;
     1935            }
     1936            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
     1937                overflow = WEEKDAY;
     1938            }
     1939
     1940            getParsingFlags(m).overflow = overflow;
     1941        }
     1942
     1943        return m;
     1944    }
     1945
     1946    // iso 8601 regex
     1947    // 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)
     1948    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)?)?/;
     1949    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)?)?/;
     1950
     1951    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
     1952
     1953    var isoDates = [
     1954        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
     1955        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
     1956        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
     1957        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
     1958        ['YYYY-DDD', /\d{4}-\d{3}/],
     1959        ['YYYY-MM', /\d{4}-\d\d/, false],
     1960        ['YYYYYYMMDD', /[+-]\d{10}/],
     1961        ['YYYYMMDD', /\d{8}/],
     1962        // YYYYMM is NOT allowed by the standard
     1963        ['GGGG[W]WWE', /\d{4}W\d{3}/],
     1964        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
     1965        ['YYYYDDD', /\d{7}/]
     1966    ];
     1967
     1968    // iso time formats and regexes
     1969    var isoTimes = [
     1970        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
     1971        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
     1972        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
     1973        ['HH:mm', /\d\d:\d\d/],
     1974        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
     1975        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
     1976        ['HHmmss', /\d\d\d\d\d\d/],
     1977        ['HHmm', /\d\d\d\d/],
     1978        ['HH', /\d\d/]
     1979    ];
     1980
     1981    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
     1982
     1983    // date from iso format
     1984    function configFromISO(config) {
     1985        var i, l,
     1986            string = config._i,
     1987            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
     1988            allowTime, dateFormat, timeFormat, tzFormat;
     1989
     1990        if (match) {
     1991            getParsingFlags(config).iso = true;
     1992
     1993            for (i = 0, l = isoDates.length; i < l; i++) {
     1994                if (isoDates[i][1].exec(match[1])) {
     1995                    dateFormat = isoDates[i][0];
     1996                    allowTime = isoDates[i][2] !== false;
     1997                    break;
     1998                }
     1999            }
     2000            if (dateFormat == null) {
     2001                config._isValid = false;
     2002                return;
     2003            }
     2004            if (match[3]) {
     2005                for (i = 0, l = isoTimes.length; i < l; i++) {
     2006                    if (isoTimes[i][1].exec(match[3])) {
     2007                        // match[2] should be 'T' or space
     2008                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
     2009                        break;
     2010                    }
     2011                }
     2012                if (timeFormat == null) {
     2013                    config._isValid = false;
     2014                    return;
     2015                }
     2016            }
     2017            if (!allowTime && timeFormat != null) {
     2018                config._isValid = false;
     2019                return;
     2020            }
     2021            if (match[4]) {
     2022                if (tzRegex.exec(match[4])) {
     2023                    tzFormat = 'Z';
     2024                } else {
     2025                    config._isValid = false;
     2026                    return;
     2027                }
     2028            }
     2029            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
     2030            configFromStringAndFormat(config);
     2031        } else {
     2032            config._isValid = false;
     2033        }
     2034    }
     2035
     2036    // date from iso format or fallback
     2037    function configFromString(config) {
     2038        var matched = aspNetJsonRegex.exec(config._i);
     2039
     2040        if (matched !== null) {
     2041            config._d = new Date(+matched[1]);
     2042            return;
     2043        }
     2044
     2045        configFromISO(config);
     2046        if (config._isValid === false) {
     2047            delete config._isValid;
     2048            utils_hooks__hooks.createFromInputFallback(config);
     2049        }
     2050    }
     2051
     2052    utils_hooks__hooks.createFromInputFallback = deprecate(
     2053        'value provided is not in a recognized ISO format. moment construction falls back to js Date(), ' +
     2054        'which is not reliable across all browsers and versions. Non ISO date formats are ' +
     2055        'discouraged and will be removed in an upcoming major release. Please refer to ' +
     2056        'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
     2057        function (config) {
     2058            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
     2059        }
     2060    );
     2061
     2062    // Pick the first defined of two or three arguments.
     2063    function defaults(a, b, c) {
     2064        if (a != null) {
     2065            return a;
     2066        }
     2067        if (b != null) {
     2068            return b;
     2069        }
     2070        return c;
     2071    }
     2072
     2073    function currentDateArray(config) {
     2074        // hooks is actually the exported moment object
     2075        var nowValue = new Date(utils_hooks__hooks.now());
     2076        if (config._useUTC) {
     2077            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
     2078        }
     2079        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
     2080    }
     2081
     2082    // convert an array to a date.
     2083    // the array should mirror the parameters below
     2084    // note: all values past the year are optional and will default to the lowest possible value.
     2085    // [year, month, day , hour, minute, second, millisecond]
     2086    function configFromArray (config) {
     2087        var i, date, input = [], currentDate, yearToUse;
     2088
     2089        if (config._d) {
     2090            return;
     2091        }
     2092
     2093        currentDate = currentDateArray(config);
     2094
     2095        //compute day of the year from weeks and weekdays
     2096        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
     2097            dayOfYearFromWeekInfo(config);
     2098        }
     2099
     2100        //if the day of the year is set, figure out what it is
     2101        if (config._dayOfYear) {
     2102            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
     2103
     2104            if (config._dayOfYear > daysInYear(yearToUse)) {
     2105                getParsingFlags(config)._overflowDayOfYear = true;
     2106            }
     2107
     2108            date = createUTCDate(yearToUse, 0, config._dayOfYear);
     2109            config._a[MONTH] = date.getUTCMonth();
     2110            config._a[DATE] = date.getUTCDate();
     2111        }
     2112
     2113        // Default to current date.
     2114        // * if no year, month, day of month are given, default to today
     2115        // * if day of month is given, default month and year
     2116        // * if month is given, default only year
     2117        // * if year is given, don't default anything
     2118        for (i = 0; i < 3 && config._a[i] == null; ++i) {
     2119            config._a[i] = input[i] = currentDate[i];
     2120        }
     2121
     2122        // Zero out whatever was not defaulted, including time
     2123        for (; i < 7; i++) {
     2124            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
     2125        }
     2126
     2127        // Check for 24:00:00.000
     2128        if (config._a[HOUR] === 24 &&
     2129                config._a[MINUTE] === 0 &&
     2130                config._a[SECOND] === 0 &&
     2131                config._a[MILLISECOND] === 0) {
     2132            config._nextDay = true;
     2133            config._a[HOUR] = 0;
     2134        }
     2135
     2136        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
     2137        // Apply timezone offset from input. The actual utcOffset can be changed
     2138        // with parseZone.
     2139        if (config._tzm != null) {
     2140            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
     2141        }
     2142
     2143        if (config._nextDay) {
     2144            config._a[HOUR] = 24;
     2145        }
     2146    }
     2147
     2148    function dayOfYearFromWeekInfo(config) {
     2149        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
     2150
     2151        w = config._w;
     2152        if (w.GG != null || w.W != null || w.E != null) {
     2153            dow = 1;
     2154            doy = 4;
     2155
     2156            // TODO: We need to take the current isoWeekYear, but that depends on
     2157            // how we interpret now (local, utc, fixed offset). So create
     2158            // a now version of current config (take local/utc/offset flags, and
     2159            // create now).
     2160            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
     2161            week = defaults(w.W, 1);
     2162            weekday = defaults(w.E, 1);
     2163            if (weekday < 1 || weekday > 7) {
     2164                weekdayOverflow = true;
     2165            }
     2166        } else {
     2167            dow = config._locale._week.dow;
     2168            doy = config._locale._week.doy;
     2169
     2170            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
     2171            week = defaults(w.w, 1);
     2172
     2173            if (w.d != null) {
     2174                // weekday -- low day numbers are considered next week
     2175                weekday = w.d;
     2176                if (weekday < 0 || weekday > 6) {
     2177                    weekdayOverflow = true;
     2178                }
     2179            } else if (w.e != null) {
     2180                // local weekday -- counting starts from begining of week
     2181                weekday = w.e + dow;
     2182                if (w.e < 0 || w.e > 6) {
     2183                    weekdayOverflow = true;
     2184                }
     2185            } else {
     2186                // default to begining of week
     2187                weekday = dow;
     2188            }
     2189        }
     2190        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
     2191            getParsingFlags(config)._overflowWeeks = true;
     2192        } else if (weekdayOverflow != null) {
     2193            getParsingFlags(config)._overflowWeekday = true;
     2194        } else {
     2195            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
     2196            config._a[YEAR] = temp.year;
     2197            config._dayOfYear = temp.dayOfYear;
     2198        }
     2199    }
     2200
     2201    // constant that refers to the ISO standard
     2202    utils_hooks__hooks.ISO_8601 = function () {};
     2203
     2204    // date from string and format string
     2205    function configFromStringAndFormat(config) {
     2206        // TODO: Move this to another part of the creation flow to prevent circular deps
     2207        if (config._f === utils_hooks__hooks.ISO_8601) {
     2208            configFromISO(config);
     2209            return;
     2210        }
     2211
     2212        config._a = [];
     2213        getParsingFlags(config).empty = true;
     2214
     2215        // This array is used to make a Date, either with `new Date` or `Date.UTC`
     2216        var string = '' + config._i,
     2217            i, parsedInput, tokens, token, skipped,
     2218            stringLength = string.length,
     2219            totalParsedInputLength = 0;
     2220
     2221        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
     2222
     2223        for (i = 0; i < tokens.length; i++) {
     2224            token = tokens[i];
     2225            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
     2226            // console.log('token', token, 'parsedInput', parsedInput,
     2227            //         'regex', getParseRegexForToken(token, config));
     2228            if (parsedInput) {
     2229                skipped = string.substr(0, string.indexOf(parsedInput));
     2230                if (skipped.length > 0) {
     2231                    getParsingFlags(config).unusedInput.push(skipped);
     2232                }
     2233                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
     2234                totalParsedInputLength += parsedInput.length;
     2235            }
     2236            // don't parse if it's not a known token
     2237            if (formatTokenFunctions[token]) {
     2238                if (parsedInput) {
     2239                    getParsingFlags(config).empty = false;
     2240                }
     2241                else {
     2242                    getParsingFlags(config).unusedTokens.push(token);
     2243                }
     2244                addTimeToArrayFromToken(token, parsedInput, config);
     2245            }
     2246            else if (config._strict && !parsedInput) {
     2247                getParsingFlags(config).unusedTokens.push(token);
     2248            }
     2249        }
     2250
     2251        // add remaining unparsed input length to the string
     2252        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
     2253        if (string.length > 0) {
     2254            getParsingFlags(config).unusedInput.push(string);
     2255        }
     2256
     2257        // clear _12h flag if hour is <= 12
     2258        if (config._a[HOUR] <= 12 &&
     2259            getParsingFlags(config).bigHour === true &&
     2260            config._a[HOUR] > 0) {
     2261            getParsingFlags(config).bigHour = undefined;
     2262        }
     2263
     2264        getParsingFlags(config).parsedDateParts = config._a.slice(0);
     2265        getParsingFlags(config).meridiem = config._meridiem;
     2266        // handle meridiem
     2267        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
     2268
     2269        configFromArray(config);
     2270        checkOverflow(config);
     2271    }
     2272
     2273
     2274    function meridiemFixWrap (locale, hour, meridiem) {
     2275        var isPm;
     2276
     2277        if (meridiem == null) {
     2278            // nothing to do
     2279            return hour;
     2280        }
     2281        if (locale.meridiemHour != null) {
     2282            return locale.meridiemHour(hour, meridiem);
     2283        } else if (locale.isPM != null) {
     2284            // Fallback
     2285            isPm = locale.isPM(meridiem);
     2286            if (isPm && hour < 12) {
     2287                hour += 12;
     2288            }
     2289            if (!isPm && hour === 12) {
     2290                hour = 0;
     2291            }
     2292            return hour;
     2293        } else {
     2294            // this is not supposed to happen
     2295            return hour;
     2296        }
     2297    }
     2298
     2299    // date from string and array of format strings
     2300    function configFromStringAndArray(config) {
     2301        var tempConfig,
     2302            bestMoment,
     2303
     2304            scoreToBeat,
     2305            i,
     2306            currentScore;
     2307
     2308        if (config._f.length === 0) {
     2309            getParsingFlags(config).invalidFormat = true;
     2310            config._d = new Date(NaN);
     2311            return;
     2312        }
     2313
     2314        for (i = 0; i < config._f.length; i++) {
     2315            currentScore = 0;
     2316            tempConfig = copyConfig({}, config);
     2317            if (config._useUTC != null) {
     2318                tempConfig._useUTC = config._useUTC;
     2319            }
     2320            tempConfig._f = config._f[i];
     2321            configFromStringAndFormat(tempConfig);
     2322
     2323            if (!valid__isValid(tempConfig)) {
     2324                continue;
     2325            }
     2326
     2327            // if there is any input that was not parsed add a penalty for that format
     2328            currentScore += getParsingFlags(tempConfig).charsLeftOver;
     2329
     2330            //or tokens
     2331            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
     2332
     2333            getParsingFlags(tempConfig).score = currentScore;
     2334
     2335            if (scoreToBeat == null || currentScore < scoreToBeat) {
     2336                scoreToBeat = currentScore;
     2337                bestMoment = tempConfig;
     2338            }
     2339        }
     2340
     2341        extend(config, bestMoment || tempConfig);
     2342    }
     2343
     2344    function configFromObject(config) {
     2345        if (config._d) {
     2346            return;
     2347        }
     2348
     2349        var i = normalizeObjectUnits(config._i);
     2350        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
     2351            return obj && parseInt(obj, 10);
     2352        });
     2353
     2354        configFromArray(config);
     2355    }
     2356
     2357    function createFromConfig (config) {
     2358        var res = new Moment(checkOverflow(prepareConfig(config)));
     2359        if (res._nextDay) {
     2360            // Adding is smart enough around DST
     2361            res.add(1, 'd');
     2362            res._nextDay = undefined;
     2363        }
     2364
     2365        return res;
     2366    }
     2367
     2368    function prepareConfig (config) {
     2369        var input = config._i,
     2370            format = config._f;
     2371
     2372        config._locale = config._locale || locale_locales__getLocale(config._l);
     2373
     2374        if (input === null || (format === undefined && input === '')) {
     2375            return valid__createInvalid({nullInput: true});
     2376        }
     2377
     2378        if (typeof input === 'string') {
     2379            config._i = input = config._locale.preparse(input);
     2380        }
     2381
     2382        if (isMoment(input)) {
     2383            return new Moment(checkOverflow(input));
     2384        } else if (isArray(format)) {
     2385            configFromStringAndArray(config);
     2386        } else if (isDate(input)) {
     2387            config._d = input;
     2388        } else if (format) {
     2389            configFromStringAndFormat(config);
     2390        }  else {
     2391            configFromInput(config);
     2392        }
     2393
     2394        if (!valid__isValid(config)) {
     2395            config._d = null;
     2396        }
     2397
     2398        return config;
     2399    }
     2400
     2401    function configFromInput(config) {
     2402        var input = config._i;
     2403        if (input === undefined) {
     2404            config._d = new Date(utils_hooks__hooks.now());
     2405        } else if (isDate(input)) {
     2406            config._d = new Date(input.valueOf());
     2407        } else if (typeof input === 'string') {
     2408            configFromString(config);
     2409        } else if (isArray(input)) {
     2410            config._a = map(input.slice(0), function (obj) {
     2411                return parseInt(obj, 10);
     2412            });
     2413            configFromArray(config);
     2414        } else if (typeof(input) === 'object') {
     2415            configFromObject(config);
     2416        } else if (typeof(input) === 'number') {
     2417            // from milliseconds
     2418            config._d = new Date(input);
     2419        } else {
     2420            utils_hooks__hooks.createFromInputFallback(config);
     2421        }
     2422    }
     2423
     2424    function createLocalOrUTC (input, format, locale, strict, isUTC) {
     2425        var c = {};
     2426
     2427        if (typeof(locale) === 'boolean') {
     2428            strict = locale;
     2429            locale = undefined;
     2430        }
     2431
     2432        if ((isObject(input) && isObjectEmpty(input)) ||
     2433                (isArray(input) && input.length === 0)) {
     2434            input = undefined;
     2435        }
     2436        // object construction must be done this way.
     2437        // https://github.com/moment/moment/issues/1423
     2438        c._isAMomentObject = true;
     2439        c._useUTC = c._isUTC = isUTC;
     2440        c._l = locale;
     2441        c._i = input;
     2442        c._f = format;
     2443        c._strict = strict;
     2444
     2445        return createFromConfig(c);
     2446    }
     2447
     2448    function local__createLocal (input, format, locale, strict) {
     2449        return createLocalOrUTC(input, format, locale, strict, false);
     2450    }
     2451
     2452    var prototypeMin = deprecate(
     2453        'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
     2454        function () {
     2455            var other = local__createLocal.apply(null, arguments);
     2456            if (this.isValid() && other.isValid()) {
     2457                return other < this ? this : other;
     2458            } else {
     2459                return valid__createInvalid();
     2460            }
     2461        }
     2462    );
     2463
     2464    var prototypeMax = deprecate(
     2465        'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
     2466        function () {
     2467            var other = local__createLocal.apply(null, arguments);
     2468            if (this.isValid() && other.isValid()) {
     2469                return other > this ? this : other;
     2470            } else {
     2471                return valid__createInvalid();
     2472            }
     2473        }
     2474    );
     2475
     2476    // Pick a moment m from moments so that m[fn](other) is true for all
     2477    // other. This relies on the function fn to be transitive.
     2478    //
     2479    // moments should either be an array of moment objects or an array, whose
     2480    // first element is an array of moment objects.
     2481    function pickBy(fn, moments) {
     2482        var res, i;
     2483        if (moments.length === 1 && isArray(moments[0])) {
     2484            moments = moments[0];
     2485        }
     2486        if (!moments.length) {
     2487            return local__createLocal();
     2488        }
     2489        res = moments[0];
     2490        for (i = 1; i < moments.length; ++i) {
     2491            if (!moments[i].isValid() || moments[i][fn](res)) {
     2492                res = moments[i];
     2493            }
     2494        }
     2495        return res;
     2496    }
     2497
     2498    // TODO: Use [].sort instead?
     2499    function min () {
     2500        var args = [].slice.call(arguments, 0);
     2501
     2502        return pickBy('isBefore', args);
     2503    }
     2504
     2505    function max () {
     2506        var args = [].slice.call(arguments, 0);
     2507
     2508        return pickBy('isAfter', args);
     2509    }
     2510
     2511    var now = function () {
     2512        return Date.now ? Date.now() : +(new Date());
     2513    };
     2514
     2515    function Duration (duration) {
     2516        var normalizedInput = normalizeObjectUnits(duration),
     2517            years = normalizedInput.year || 0,
     2518            quarters = normalizedInput.quarter || 0,
     2519            months = normalizedInput.month || 0,
     2520            weeks = normalizedInput.week || 0,
     2521            days = normalizedInput.day || 0,
     2522            hours = normalizedInput.hour || 0,
     2523            minutes = normalizedInput.minute || 0,
     2524            seconds = normalizedInput.second || 0,
     2525            milliseconds = normalizedInput.millisecond || 0;
     2526
     2527        // representation for dateAddRemove
     2528        this._milliseconds = +milliseconds +
     2529            seconds * 1e3 + // 1000
     2530            minutes * 6e4 + // 1000 * 60
     2531            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
     2532        // Because of dateAddRemove treats 24 hours as different from a
     2533        // day when working around DST, we need to store them separately
     2534        this._days = +days +
     2535            weeks * 7;
     2536        // It is impossible translate months into days without knowing
     2537        // which months you are are talking about, so we have to store
     2538        // it separately.
     2539        this._months = +months +
     2540            quarters * 3 +
     2541            years * 12;
     2542
     2543        this._data = {};
     2544
     2545        this._locale = locale_locales__getLocale();
     2546
     2547        this._bubble();
     2548    }
     2549
     2550    function isDuration (obj) {
     2551        return obj instanceof Duration;
     2552    }
     2553
     2554    function absRound (number) {
     2555        if (number < 0) {
     2556            return Math.round(-1 * number) * -1;
     2557        } else {
     2558            return Math.round(number);
     2559        }
     2560    }
     2561
    31882562    // FORMATTING
    31892563
     2564    function offset (token, separator) {
     2565        addFormatToken(token, 0, 0, function () {
     2566            var offset = this.utcOffset();
     2567            var sign = '+';
     2568            if (offset < 0) {
     2569                offset = -offset;
     2570                sign = '-';
     2571            }
     2572            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
     2573        });
     2574    }
     2575
     2576    offset('Z', ':');
     2577    offset('ZZ', '');
     2578
     2579    // PARSING
     2580
     2581    addRegexToken('Z',  matchShortOffset);
     2582    addRegexToken('ZZ', matchShortOffset);
     2583    addParseToken(['Z', 'ZZ'], function (input, array, config) {
     2584        config._useUTC = true;
     2585        config._tzm = offsetFromString(matchShortOffset, input);
     2586    });
     2587
     2588    // HELPERS
     2589
     2590    // timezone chunker
     2591    // '+10:00' > ['10',  '00']
     2592    // '-1530'  > ['-15', '30']
     2593    var chunkOffset = /([\+\-]|\d\d)/gi;
     2594
     2595    function offsetFromString(matcher, string) {
     2596        var matches = ((string || '').match(matcher) || []);
     2597        var chunk   = matches[matches.length - 1] || [];
     2598        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
     2599        var minutes = +(parts[1] * 60) + toInt(parts[2]);
     2600
     2601        return parts[0] === '+' ? minutes : -minutes;
     2602    }
     2603
     2604    // Return a moment from input, that is local/utc/zone equivalent to model.
     2605    function cloneWithOffset(input, model) {
     2606        var res, diff;
     2607        if (model._isUTC) {
     2608            res = model.clone();
     2609            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
     2610            // Use low-level api, because this fn is low-level api.
     2611            res._d.setTime(res._d.valueOf() + diff);
     2612            utils_hooks__hooks.updateOffset(res, false);
     2613            return res;
     2614        } else {
     2615            return local__createLocal(input).local();
     2616        }
     2617    }
     2618
     2619    function getDateOffset (m) {
     2620        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
     2621        // https://github.com/moment/moment/pull/1871
     2622        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
     2623    }
     2624
     2625    // HOOKS
     2626
     2627    // This function will be called whenever a moment is mutated.
     2628    // It is intended to keep the offset in sync with the timezone.
     2629    utils_hooks__hooks.updateOffset = function () {};
     2630
     2631    // MOMENTS
     2632
     2633    // keepLocalTime = true means only change the timezone, without
     2634    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
     2635    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
     2636    // +0200, so we adjust the time as needed, to be valid.
     2637    //
     2638    // Keeping the time actually adds/subtracts (one hour)
     2639    // from the actual represented time. That is why we call updateOffset
     2640    // a second time. In case it wants us to change the offset again
     2641    // _changeInProgress == true case, then we have to adjust, because
     2642    // there is no such time in the given timezone.
     2643    function getSetOffset (input, keepLocalTime) {
     2644        var offset = this._offset || 0,
     2645            localAdjust;
     2646        if (!this.isValid()) {
     2647            return input != null ? this : NaN;
     2648        }
     2649        if (input != null) {
     2650            if (typeof input === 'string') {
     2651                input = offsetFromString(matchShortOffset, input);
     2652            } else if (Math.abs(input) < 16) {
     2653                input = input * 60;
     2654            }
     2655            if (!this._isUTC && keepLocalTime) {
     2656                localAdjust = getDateOffset(this);
     2657            }
     2658            this._offset = input;
     2659            this._isUTC = true;
     2660            if (localAdjust != null) {
     2661                this.add(localAdjust, 'm');
     2662            }
     2663            if (offset !== input) {
     2664                if (!keepLocalTime || this._changeInProgress) {
     2665                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
     2666                } else if (!this._changeInProgress) {
     2667                    this._changeInProgress = true;
     2668                    utils_hooks__hooks.updateOffset(this, true);
     2669                    this._changeInProgress = null;
     2670                }
     2671            }
     2672            return this;
     2673        } else {
     2674            return this._isUTC ? offset : getDateOffset(this);
     2675        }
     2676    }
     2677
     2678    function getSetZone (input, keepLocalTime) {
     2679        if (input != null) {
     2680            if (typeof input !== 'string') {
     2681                input = -input;
     2682            }
     2683
     2684            this.utcOffset(input, keepLocalTime);
     2685
     2686            return this;
     2687        } else {
     2688            return -this.utcOffset();
     2689        }
     2690    }
     2691
     2692    function setOffsetToUTC (keepLocalTime) {
     2693        return this.utcOffset(0, keepLocalTime);
     2694    }
     2695
     2696    function setOffsetToLocal (keepLocalTime) {
     2697        if (this._isUTC) {
     2698            this.utcOffset(0, keepLocalTime);
     2699            this._isUTC = false;
     2700
     2701            if (keepLocalTime) {
     2702                this.subtract(getDateOffset(this), 'm');
     2703            }
     2704        }
     2705        return this;
     2706    }
     2707
     2708    function setOffsetToParsedOffset () {
     2709        if (this._tzm) {
     2710            this.utcOffset(this._tzm);
     2711        } else if (typeof this._i === 'string') {
     2712            var tZone = offsetFromString(matchOffset, this._i);
     2713
     2714            if (tZone === 0) {
     2715                this.utcOffset(0, true);
     2716            } else {
     2717                this.utcOffset(offsetFromString(matchOffset, this._i));
     2718            }
     2719        }
     2720        return this;
     2721    }
     2722
     2723    function hasAlignedHourOffset (input) {
     2724        if (!this.isValid()) {
     2725            return false;
     2726        }
     2727        input = input ? local__createLocal(input).utcOffset() : 0;
     2728
     2729        return (this.utcOffset() - input) % 60 === 0;
     2730    }
     2731
     2732    function isDaylightSavingTime () {
     2733        return (
     2734            this.utcOffset() > this.clone().month(0).utcOffset() ||
     2735            this.utcOffset() > this.clone().month(5).utcOffset()
     2736        );
     2737    }
     2738
     2739    function isDaylightSavingTimeShifted () {
     2740        if (!isUndefined(this._isDSTShifted)) {
     2741            return this._isDSTShifted;
     2742        }
     2743
     2744        var c = {};
     2745
     2746        copyConfig(c, this);
     2747        c = prepareConfig(c);
     2748
     2749        if (c._a) {
     2750            var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
     2751            this._isDSTShifted = this.isValid() &&
     2752                compareArrays(c._a, other.toArray()) > 0;
     2753        } else {
     2754            this._isDSTShifted = false;
     2755        }
     2756
     2757        return this._isDSTShifted;
     2758    }
     2759
     2760    function isLocal () {
     2761        return this.isValid() ? !this._isUTC : false;
     2762    }
     2763
     2764    function isUtcOffset () {
     2765        return this.isValid() ? this._isUTC : false;
     2766    }
     2767
     2768    function isUtc () {
     2769        return this.isValid() ? this._isUTC && this._offset === 0 : false;
     2770    }
     2771
     2772    // ASP.NET json date format regex
     2773    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
     2774
     2775    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
     2776    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
     2777    // and further modified to allow for strings containing both week and day
     2778    var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
     2779
     2780    function create__createDuration (input, key) {
     2781        var duration = input,
     2782            // matching against regexp is expensive, do it on demand
     2783            match = null,
     2784            sign,
     2785            ret,
     2786            diffRes;
     2787
     2788        if (isDuration(input)) {
     2789            duration = {
     2790                ms : input._milliseconds,
     2791                d  : input._days,
     2792                M  : input._months
     2793            };
     2794        } else if (typeof input === 'number') {
     2795            duration = {};
     2796            if (key) {
     2797                duration[key] = input;
     2798            } else {
     2799                duration.milliseconds = input;
     2800            }
     2801        } else if (!!(match = aspNetRegex.exec(input))) {
     2802            sign = (match[1] === '-') ? -1 : 1;
     2803            duration = {
     2804                y  : 0,
     2805                d  : toInt(match[DATE])                         * sign,
     2806                h  : toInt(match[HOUR])                         * sign,
     2807                m  : toInt(match[MINUTE])                       * sign,
     2808                s  : toInt(match[SECOND])                       * sign,
     2809                ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
     2810            };
     2811        } else if (!!(match = isoRegex.exec(input))) {
     2812            sign = (match[1] === '-') ? -1 : 1;
     2813            duration = {
     2814                y : parseIso(match[2], sign),
     2815                M : parseIso(match[3], sign),
     2816                w : parseIso(match[4], sign),
     2817                d : parseIso(match[5], sign),
     2818                h : parseIso(match[6], sign),
     2819                m : parseIso(match[7], sign),
     2820                s : parseIso(match[8], sign)
     2821            };
     2822        } else if (duration == null) {// checks for null or undefined
     2823            duration = {};
     2824        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
     2825            diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
     2826
     2827            duration = {};
     2828            duration.ms = diffRes.milliseconds;
     2829            duration.M = diffRes.months;
     2830        }
     2831
     2832        ret = new Duration(duration);
     2833
     2834        if (isDuration(input) && hasOwnProp(input, '_locale')) {
     2835            ret._locale = input._locale;
     2836        }
     2837
     2838        return ret;
     2839    }
     2840
     2841    create__createDuration.fn = Duration.prototype;
     2842
     2843    function parseIso (inp, sign) {
     2844        // We'd normally use ~~inp for this, but unfortunately it also
     2845        // converts floats to ints.
     2846        // inp may be undefined, so careful calling replace on it.
     2847        var res = inp && parseFloat(inp.replace(',', '.'));
     2848        // apply sign while we're at it
     2849        return (isNaN(res) ? 0 : res) * sign;
     2850    }
     2851
     2852    function positiveMomentsDifference(base, other) {
     2853        var res = {milliseconds: 0, months: 0};
     2854
     2855        res.months = other.month() - base.month() +
     2856            (other.year() - base.year()) * 12;
     2857        if (base.clone().add(res.months, 'M').isAfter(other)) {
     2858            --res.months;
     2859        }
     2860
     2861        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
     2862
     2863        return res;
     2864    }
     2865
     2866    function momentsDifference(base, other) {
     2867        var res;
     2868        if (!(base.isValid() && other.isValid())) {
     2869            return {milliseconds: 0, months: 0};
     2870        }
     2871
     2872        other = cloneWithOffset(other, base);
     2873        if (base.isBefore(other)) {
     2874            res = positiveMomentsDifference(base, other);
     2875        } else {
     2876            res = positiveMomentsDifference(other, base);
     2877            res.milliseconds = -res.milliseconds;
     2878            res.months = -res.months;
     2879        }
     2880
     2881        return res;
     2882    }
     2883
     2884    // TODO: remove 'name' arg after deprecation is removed
     2885    function createAdder(direction, name) {
     2886        return function (val, period) {
     2887            var dur, tmp;
     2888            //invert the arguments, but complain about it
     2889            if (period !== null && !isNaN(+period)) {
     2890                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
     2891                'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
     2892                tmp = val; val = period; period = tmp;
     2893            }
     2894
     2895            val = typeof val === 'string' ? +val : val;
     2896            dur = create__createDuration(val, period);
     2897            add_subtract__addSubtract(this, dur, direction);
     2898            return this;
     2899        };
     2900    }
     2901
     2902    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
     2903        var milliseconds = duration._milliseconds,
     2904            days = absRound(duration._days),
     2905            months = absRound(duration._months);
     2906
     2907        if (!mom.isValid()) {
     2908            // No op
     2909            return;
     2910        }
     2911
     2912        updateOffset = updateOffset == null ? true : updateOffset;
     2913
     2914        if (milliseconds) {
     2915            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
     2916        }
     2917        if (days) {
     2918            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
     2919        }
     2920        if (months) {
     2921            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
     2922        }
     2923        if (updateOffset) {
     2924            utils_hooks__hooks.updateOffset(mom, days || months);
     2925        }
     2926    }
     2927
     2928    var add_subtract__add      = createAdder(1, 'add');
     2929    var add_subtract__subtract = createAdder(-1, 'subtract');
     2930
     2931    function getCalendarFormat(myMoment, now) {
     2932        var diff = myMoment.diff(now, 'days', true);
     2933        return diff < -6 ? 'sameElse' :
     2934                diff < -1 ? 'lastWeek' :
     2935                diff < 0 ? 'lastDay' :
     2936                diff < 1 ? 'sameDay' :
     2937                diff < 2 ? 'nextDay' :
     2938                diff < 7 ? 'nextWeek' : 'sameElse';
     2939    }
     2940
     2941    function moment_calendar__calendar (time, formats) {
     2942        // We want to compare the start of today, vs this.
     2943        // Getting start-of-today depends on whether we're local/utc/offset or not.
     2944        var now = time || local__createLocal(),
     2945            sod = cloneWithOffset(now, this).startOf('day'),
     2946            format = utils_hooks__hooks.calendarFormat(this, sod) || 'sameElse';
     2947
     2948        var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
     2949
     2950        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
     2951    }
     2952
     2953    function clone () {
     2954        return new Moment(this);
     2955    }
     2956
     2957    function isAfter (input, units) {
     2958        var localInput = isMoment(input) ? input : local__createLocal(input);
     2959        if (!(this.isValid() && localInput.isValid())) {
     2960            return false;
     2961        }
     2962        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
     2963        if (units === 'millisecond') {
     2964            return this.valueOf() > localInput.valueOf();
     2965        } else {
     2966            return localInput.valueOf() < this.clone().startOf(units).valueOf();
     2967        }
     2968    }
     2969
     2970    function isBefore (input, units) {
     2971        var localInput = isMoment(input) ? input : local__createLocal(input);
     2972        if (!(this.isValid() && localInput.isValid())) {
     2973            return false;
     2974        }
     2975        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
     2976        if (units === 'millisecond') {
     2977            return this.valueOf() < localInput.valueOf();
     2978        } else {
     2979            return this.clone().endOf(units).valueOf() < localInput.valueOf();
     2980        }
     2981    }
     2982
     2983    function isBetween (from, to, units, inclusivity) {
     2984        inclusivity = inclusivity || '()';
     2985        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
     2986            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
     2987    }
     2988
     2989    function isSame (input, units) {
     2990        var localInput = isMoment(input) ? input : local__createLocal(input),
     2991            inputMs;
     2992        if (!(this.isValid() && localInput.isValid())) {
     2993            return false;
     2994        }
     2995        units = normalizeUnits(units || 'millisecond');
     2996        if (units === 'millisecond') {
     2997            return this.valueOf() === localInput.valueOf();
     2998        } else {
     2999            inputMs = localInput.valueOf();
     3000            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
     3001        }
     3002    }
     3003
     3004    function isSameOrAfter (input, units) {
     3005        return this.isSame(input, units) || this.isAfter(input,units);
     3006    }
     3007
     3008    function isSameOrBefore (input, units) {
     3009        return this.isSame(input, units) || this.isBefore(input,units);
     3010    }
     3011
     3012    function diff (input, units, asFloat) {
     3013        var that,
     3014            zoneDelta,
     3015            delta, output;
     3016
     3017        if (!this.isValid()) {
     3018            return NaN;
     3019        }
     3020
     3021        that = cloneWithOffset(input, this);
     3022
     3023        if (!that.isValid()) {
     3024            return NaN;
     3025        }
     3026
     3027        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
     3028
     3029        units = normalizeUnits(units);
     3030
     3031        if (units === 'year' || units === 'month' || units === 'quarter') {
     3032            output = monthDiff(this, that);
     3033            if (units === 'quarter') {
     3034                output = output / 3;
     3035            } else if (units === 'year') {
     3036                output = output / 12;
     3037            }
     3038        } else {
     3039            delta = this - that;
     3040            output = units === 'second' ? delta / 1e3 : // 1000
     3041                units === 'minute' ? delta / 6e4 : // 1000 * 60
     3042                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
     3043                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
     3044                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
     3045                delta;
     3046        }
     3047        return asFloat ? output : absFloor(output);
     3048    }
     3049
     3050    function monthDiff (a, b) {
     3051        // difference in months
     3052        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
     3053            // b is in (anchor - 1 month, anchor + 1 month)
     3054            anchor = a.clone().add(wholeMonthDiff, 'months'),
     3055            anchor2, adjust;
     3056
     3057        if (b - anchor < 0) {
     3058            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
     3059            // linear across the month
     3060            adjust = (b - anchor) / (anchor - anchor2);
     3061        } else {
     3062            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
     3063            // linear across the month
     3064            adjust = (b - anchor) / (anchor2 - anchor);
     3065        }
     3066
     3067        //check for negative zero, return zero if negative zero
     3068        return -(wholeMonthDiff + adjust) || 0;
     3069    }
     3070
     3071    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
     3072    utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
     3073
     3074    function toString () {
     3075        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
     3076    }
     3077
     3078    function moment_format__toISOString () {
     3079        var m = this.clone().utc();
     3080        if (0 < m.year() && m.year() <= 9999) {
     3081            if (isFunction(Date.prototype.toISOString)) {
     3082                // native implementation is ~50x faster, use it when we can
     3083                return this.toDate().toISOString();
     3084            } else {
     3085                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
     3086            }
     3087        } else {
     3088            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
     3089        }
     3090    }
     3091
     3092    function format (inputString) {
     3093        if (!inputString) {
     3094            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
     3095        }
     3096        var output = formatMoment(this, inputString);
     3097        return this.localeData().postformat(output);
     3098    }
     3099
     3100    function from (time, withoutSuffix) {
     3101        if (this.isValid() &&
     3102                ((isMoment(time) && time.isValid()) ||
     3103                 local__createLocal(time).isValid())) {
     3104            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
     3105        } else {
     3106            return this.localeData().invalidDate();
     3107        }
     3108    }
     3109
     3110    function fromNow (withoutSuffix) {
     3111        return this.from(local__createLocal(), withoutSuffix);
     3112    }
     3113
     3114    function to (time, withoutSuffix) {
     3115        if (this.isValid() &&
     3116                ((isMoment(time) && time.isValid()) ||
     3117                 local__createLocal(time).isValid())) {
     3118            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
     3119        } else {
     3120            return this.localeData().invalidDate();
     3121        }
     3122    }
     3123
     3124    function toNow (withoutSuffix) {
     3125        return this.to(local__createLocal(), withoutSuffix);
     3126    }
     3127
     3128    // If passed a locale key, it will set the locale for this
     3129    // instance.  Otherwise, it will return the locale configuration
     3130    // variables for this instance.
     3131    function locale (key) {
     3132        var newLocaleData;
     3133
     3134        if (key === undefined) {
     3135            return this._locale._abbr;
     3136        } else {
     3137            newLocaleData = locale_locales__getLocale(key);
     3138            if (newLocaleData != null) {
     3139                this._locale = newLocaleData;
     3140            }
     3141            return this;
     3142        }
     3143    }
     3144
     3145    var lang = deprecate(
     3146        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
     3147        function (key) {
     3148            if (key === undefined) {
     3149                return this.localeData();
     3150            } else {
     3151                return this.locale(key);
     3152            }
     3153        }
     3154    );
     3155
     3156    function localeData () {
     3157        return this._locale;
     3158    }
     3159
     3160    function startOf (units) {
     3161        units = normalizeUnits(units);
     3162        // the following switch intentionally omits break keywords
     3163        // to utilize falling through the cases.
     3164        switch (units) {
     3165            case 'year':
     3166                this.month(0);
     3167                /* falls through */
     3168            case 'quarter':
     3169            case 'month':
     3170                this.date(1);
     3171                /* falls through */
     3172            case 'week':
     3173            case 'isoWeek':
     3174            case 'day':
     3175            case 'date':
     3176                this.hours(0);
     3177                /* falls through */
     3178            case 'hour':
     3179                this.minutes(0);
     3180                /* falls through */
     3181            case 'minute':
     3182                this.seconds(0);
     3183                /* falls through */
     3184            case 'second':
     3185                this.milliseconds(0);
     3186        }
     3187
     3188        // weeks are a special case
     3189        if (units === 'week') {
     3190            this.weekday(0);
     3191        }
     3192        if (units === 'isoWeek') {
     3193            this.isoWeekday(1);
     3194        }
     3195
     3196        // quarters are also special
     3197        if (units === 'quarter') {
     3198            this.month(Math.floor(this.month() / 3) * 3);
     3199        }
     3200
     3201        return this;
     3202    }
     3203
     3204    function endOf (units) {
     3205        units = normalizeUnits(units);
     3206        if (units === undefined || units === 'millisecond') {
     3207            return this;
     3208        }
     3209
     3210        // 'date' is an alias for 'day', so it should be considered as such.
     3211        if (units === 'date') {
     3212            units = 'day';
     3213        }
     3214
     3215        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
     3216    }
     3217
     3218    function to_type__valueOf () {
     3219        return this._d.valueOf() - ((this._offset || 0) * 60000);
     3220    }
     3221
     3222    function unix () {
     3223        return Math.floor(this.valueOf() / 1000);
     3224    }
     3225
     3226    function toDate () {
     3227        return new Date(this.valueOf());
     3228    }
     3229
     3230    function toArray () {
     3231        var m = this;
     3232        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
     3233    }
     3234
     3235    function toObject () {
     3236        var m = this;
     3237        return {
     3238            years: m.year(),
     3239            months: m.month(),
     3240            date: m.date(),
     3241            hours: m.hours(),
     3242            minutes: m.minutes(),
     3243            seconds: m.seconds(),
     3244            milliseconds: m.milliseconds()
     3245        };
     3246    }
     3247
     3248    function toJSON () {
     3249        // new Date(NaN).toJSON() === null
     3250        return this.isValid() ? this.toISOString() : null;
     3251    }
     3252
     3253    function moment_valid__isValid () {
     3254        return valid__isValid(this);
     3255    }
     3256
     3257    function parsingFlags () {
     3258        return extend({}, getParsingFlags(this));
     3259    }
     3260
     3261    function invalidAt () {
     3262        return getParsingFlags(this).overflow;
     3263    }
     3264
     3265    function creationData() {
     3266        return {
     3267            input: this._i,
     3268            format: this._f,
     3269            locale: this._locale,
     3270            isUTC: this._isUTC,
     3271            strict: this._strict
     3272        };
     3273    }
     3274
     3275    // FORMATTING
     3276
     3277    addFormatToken(0, ['gg', 2], 0, function () {
     3278        return this.weekYear() % 100;
     3279    });
     3280
     3281    addFormatToken(0, ['GG', 2], 0, function () {
     3282        return this.isoWeekYear() % 100;
     3283    });
     3284
     3285    function addWeekYearFormatToken (token, getter) {
     3286        addFormatToken(0, [token, token.length], 0, getter);
     3287    }
     3288
     3289    addWeekYearFormatToken('gggg',     'weekYear');
     3290    addWeekYearFormatToken('ggggg',    'weekYear');
     3291    addWeekYearFormatToken('GGGG',  'isoWeekYear');
     3292    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
     3293
     3294    // ALIASES
     3295
     3296    addUnitAlias('weekYear', 'gg');
     3297    addUnitAlias('isoWeekYear', 'GG');
     3298
     3299    // PRIORITY
     3300
     3301    addUnitPriority('weekYear', 1);
     3302    addUnitPriority('isoWeekYear', 1);
     3303
     3304
     3305    // PARSING
     3306
     3307    addRegexToken('G',      matchSigned);
     3308    addRegexToken('g',      matchSigned);
     3309    addRegexToken('GG',     match1to2, match2);
     3310    addRegexToken('gg',     match1to2, match2);
     3311    addRegexToken('GGGG',   match1to4, match4);
     3312    addRegexToken('gggg',   match1to4, match4);
     3313    addRegexToken('GGGGG',  match1to6, match6);
     3314    addRegexToken('ggggg',  match1to6, match6);
     3315
     3316    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
     3317        week[token.substr(0, 2)] = toInt(input);
     3318    });
     3319
     3320    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
     3321        week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
     3322    });
     3323
     3324    // MOMENTS
     3325
     3326    function getSetWeekYear (input) {
     3327        return getSetWeekYearHelper.call(this,
     3328                input,
     3329                this.week(),
     3330                this.weekday(),
     3331                this.localeData()._week.dow,
     3332                this.localeData()._week.doy);
     3333    }
     3334
     3335    function getSetISOWeekYear (input) {
     3336        return getSetWeekYearHelper.call(this,
     3337                input, this.isoWeek(), this.isoWeekday(), 1, 4);
     3338    }
     3339
     3340    function getISOWeeksInYear () {
     3341        return weeksInYear(this.year(), 1, 4);
     3342    }
     3343
     3344    function getWeeksInYear () {
     3345        var weekInfo = this.localeData()._week;
     3346        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
     3347    }
     3348
     3349    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
     3350        var weeksTarget;
     3351        if (input == null) {
     3352            return weekOfYear(this, dow, doy).year;
     3353        } else {
     3354            weeksTarget = weeksInYear(input, dow, doy);
     3355            if (week > weeksTarget) {
     3356                week = weeksTarget;
     3357            }
     3358            return setWeekAll.call(this, input, week, weekday, dow, doy);
     3359        }
     3360    }
     3361
     3362    function setWeekAll(weekYear, week, weekday, dow, doy) {
     3363        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
     3364            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
     3365
     3366        this.year(date.getUTCFullYear());
     3367        this.month(date.getUTCMonth());
     3368        this.date(date.getUTCDate());
     3369        return this;
     3370    }
     3371
     3372    // FORMATTING
     3373
     3374    addFormatToken('Q', 0, 'Qo', 'quarter');
     3375
     3376    // ALIASES
     3377
     3378    addUnitAlias('quarter', 'Q');
     3379
     3380    // PRIORITY
     3381
     3382    addUnitPriority('quarter', 7);
     3383
     3384    // PARSING
     3385
     3386    addRegexToken('Q', match1);
     3387    addParseToken('Q', function (input, array) {
     3388        array[MONTH] = (toInt(input) - 1) * 3;
     3389    });
     3390
     3391    // MOMENTS
     3392
     3393    function getSetQuarter (input) {
     3394        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
     3395    }
     3396
     3397    // FORMATTING
     3398
     3399    addFormatToken('D', ['DD', 2], 'Do', 'date');
     3400
     3401    // ALIASES
     3402
     3403    addUnitAlias('date', 'D');
     3404
     3405    // PRIOROITY
     3406    addUnitPriority('date', 9);
     3407
     3408    // PARSING
     3409
     3410    addRegexToken('D',  match1to2);
     3411    addRegexToken('DD', match1to2, match2);
     3412    addRegexToken('Do', function (isStrict, locale) {
     3413        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
     3414    });
     3415
     3416    addParseToken(['D', 'DD'], DATE);
     3417    addParseToken('Do', function (input, array) {
     3418        array[DATE] = toInt(input.match(match1to2)[0], 10);
     3419    });
     3420
     3421    // MOMENTS
     3422
     3423    var getSetDayOfMonth = makeGetSet('Date', true);
     3424
     3425    // FORMATTING
     3426
     3427    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
     3428
     3429    // ALIASES
     3430
     3431    addUnitAlias('dayOfYear', 'DDD');
     3432
     3433    // PRIORITY
     3434    addUnitPriority('dayOfYear', 4);
     3435
     3436    // PARSING
     3437
     3438    addRegexToken('DDD',  match1to3);
     3439    addRegexToken('DDDD', match3);
     3440    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
     3441        config._dayOfYear = toInt(input);
     3442    });
     3443
     3444    // HELPERS
     3445
     3446    // MOMENTS
     3447
     3448    function getSetDayOfYear (input) {
     3449        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
     3450        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
     3451    }
     3452
     3453    // FORMATTING
     3454
    31903455    addFormatToken('m', ['mm', 2], 0, 'minute');
    31913456
     
    31933458
    31943459    addUnitAlias('minute', 'm');
     3460
     3461    // PRIORITY
     3462
     3463    addUnitPriority('minute', 14);
    31953464
    31963465    // PARSING
     
    32123481    addUnitAlias('second', 's');
    32133482
     3483    // PRIORITY
     3484
     3485    addUnitPriority('second', 15);
     3486
    32143487    // PARSING
    32153488
     
    32563529
    32573530    addUnitAlias('millisecond', 'ms');
     3531
     3532    // PRIORITY
     3533
     3534    addUnitPriority('millisecond', 16);
    32583535
    32593536    // PARSING
     
    33063583    momentPrototype__proto.to                = to;
    33073584    momentPrototype__proto.toNow             = toNow;
    3308     momentPrototype__proto.get               = getSet;
     3585    momentPrototype__proto.get               = stringGet;
    33093586    momentPrototype__proto.invalidAt         = invalidAt;
    33103587    momentPrototype__proto.isAfter           = isAfter;
     
    33213598    momentPrototype__proto.min               = prototypeMin;
    33223599    momentPrototype__proto.parsingFlags      = parsingFlags;
    3323     momentPrototype__proto.set               = getSet;
     3600    momentPrototype__proto.set               = stringSet;
    33243601    momentPrototype__proto.startOf           = startOf;
    33253602    momentPrototype__proto.subtract          = add_subtract__subtract;
     
    33813658    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
    33823659    momentPrototype__proto.isDST                = isDaylightSavingTime;
    3383     momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
    33843660    momentPrototype__proto.isLocal              = isLocal;
    33853661    momentPrototype__proto.isUtcOffset          = isUtcOffset;
     
    33953671    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
    33963672    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
    3397     momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
     3673    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
     3674    momentPrototype__proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
    33983675
    33993676    var momentPrototype = momentPrototype__proto;
     
    34073684    }
    34083685
    3409     var defaultCalendar = {
    3410         sameDay : '[Today at] LT',
    3411         nextDay : '[Tomorrow at] LT',
    3412         nextWeek : 'dddd [at] LT',
    3413         lastDay : '[Yesterday at] LT',
    3414         lastWeek : '[Last] dddd [at] LT',
    3415         sameElse : 'L'
    3416     };
    3417 
    3418     function locale_calendar__calendar (key, mom, now) {
    3419         var output = this._calendar[key];
    3420         return isFunction(output) ? output.call(mom, now) : output;
    3421     }
    3422 
    3423     var defaultLongDateFormat = {
    3424         LTS  : 'h:mm:ss A',
    3425         LT   : 'h:mm A',
    3426         L    : 'MM/DD/YYYY',
    3427         LL   : 'MMMM D, YYYY',
    3428         LLL  : 'MMMM D, YYYY h:mm A',
    3429         LLLL : 'dddd, MMMM D, YYYY h:mm A'
    3430     };
    3431 
    3432     function longDateFormat (key) {
    3433         var format = this._longDateFormat[key],
    3434             formatUpper = this._longDateFormat[key.toUpperCase()];
    3435 
    3436         if (format || !formatUpper) {
    3437             return format;
    3438         }
    3439 
    3440         this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
    3441             return val.slice(1);
    3442         });
    3443 
    3444         return this._longDateFormat[key];
    3445     }
    3446 
    3447     var defaultInvalidDate = 'Invalid date';
    3448 
    3449     function invalidDate () {
    3450         return this._invalidDate;
    3451     }
    3452 
    3453     var defaultOrdinal = '%d';
    3454     var defaultOrdinalParse = /\d{1,2}/;
    3455 
    3456     function ordinal (number) {
    3457         return this._ordinal.replace('%d', number);
    3458     }
    3459 
    34603686    function preParsePostFormat (string) {
    34613687        return string;
    34623688    }
    34633689
    3464     var defaultRelativeTime = {
    3465         future : 'in %s',
    3466         past   : '%s ago',
    3467         s  : 'a few seconds',
    3468         m  : 'a minute',
    3469         mm : '%d minutes',
    3470         h  : 'an hour',
    3471         hh : '%d hours',
    3472         d  : 'a day',
    3473         dd : '%d days',
    3474         M  : 'a month',
    3475         MM : '%d months',
    3476         y  : 'a year',
    3477         yy : '%d years'
    3478     };
    3479 
    3480     function relative__relativeTime (number, withoutSuffix, string, isFuture) {
    3481         var output = this._relativeTime[string];
    3482         return (isFunction(output)) ?
    3483             output(number, withoutSuffix, string, isFuture) :
    3484             output.replace(/%d/i, number);
    3485     }
    3486 
    3487     function pastFuture (diff, output) {
    3488         var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
    3489         return isFunction(format) ? format(output) : format.replace(/%s/i, output);
    3490     }
    3491 
    34923690    var prototype__proto = Locale.prototype;
    34933691
    3494     prototype__proto._calendar       = defaultCalendar;
    34953692    prototype__proto.calendar        = locale_calendar__calendar;
    3496     prototype__proto._longDateFormat = defaultLongDateFormat;
    34973693    prototype__proto.longDateFormat  = longDateFormat;
    3498     prototype__proto._invalidDate    = defaultInvalidDate;
    34993694    prototype__proto.invalidDate     = invalidDate;
    3500     prototype__proto._ordinal        = defaultOrdinal;
    35013695    prototype__proto.ordinal         = ordinal;
    3502     prototype__proto._ordinalParse   = defaultOrdinalParse;
    35033696    prototype__proto.preparse        = preParsePostFormat;
    35043697    prototype__proto.postformat      = preParsePostFormat;
    3505     prototype__proto._relativeTime   = defaultRelativeTime;
    35063698    prototype__proto.relativeTime    = relative__relativeTime;
    35073699    prototype__proto.pastFuture      = pastFuture;
     
    35103702    // Month
    35113703    prototype__proto.months            =        localeMonths;
    3512     prototype__proto._months           = defaultLocaleMonths;
    35133704    prototype__proto.monthsShort       =        localeMonthsShort;
    3514     prototype__proto._monthsShort      = defaultLocaleMonthsShort;
    35153705    prototype__proto.monthsParse       =        localeMonthsParse;
    3516     prototype__proto._monthsRegex      = defaultMonthsRegex;
    35173706    prototype__proto.monthsRegex       = monthsRegex;
    3518     prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
    35193707    prototype__proto.monthsShortRegex  = monthsShortRegex;
    35203708
    35213709    // Week
    35223710    prototype__proto.week = localeWeek;
    3523     prototype__proto._week = defaultLocaleWeek;
    35243711    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
    35253712    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
     
    35273714    // Day of Week
    35283715    prototype__proto.weekdays       =        localeWeekdays;
    3529     prototype__proto._weekdays      = defaultLocaleWeekdays;
    35303716    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
    3531     prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
    35323717    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
    3533     prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
    35343718    prototype__proto.weekdaysParse  =        localeWeekdaysParse;
    35353719
    3536     prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
    35373720    prototype__proto.weekdaysRegex       =        weekdaysRegex;
    3538     prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
    35393721    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
    3540     prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
    35413722    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
    35423723
    35433724    // Hours
    35443725    prototype__proto.isPM = localeIsPM;
    3545     prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
    35463726    prototype__proto.meridiem = localeMeridiem;
    35473727
     
    38704050        a[4] = locale;
    38714051        return substituteTimeAgo.apply(null, a);
     4052    }
     4053
     4054    // This function allows you to set the rounding function for relative time strings
     4055    function duration_humanize__getSetRelativeTimeRounding (roundingFunction) {
     4056        if (roundingFunction === undefined) {
     4057            return round;
     4058        }
     4059        if (typeof(roundingFunction) === 'function') {
     4060            round = roundingFunction;
     4061            return true;
     4062        }
     4063        return false;
    38724064    }
    38734065
     
    40044196
    40054197
    4006     utils_hooks__hooks.version = '2.13.0';
     4198    utils_hooks__hooks.version = '2.15.1';
    40074199
    40084200    setHookCallback(local__createLocal);
     
    40314223    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
    40324224    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
     4225    utils_hooks__hooks.relativeTimeRounding = duration_humanize__getSetRelativeTimeRounding;
    40334226    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
     4227    utils_hooks__hooks.calendarFormat        = getCalendarFormat;
    40344228    utils_hooks__hooks.prototype             = momentPrototype;
    40354229
Note: See TracChangeset for help on using the changeset viewer.